//
//  AppController.m
//  This file is part of D&D Manager
//
//  Created by Matthew Hutton on 01/10/2006.
//
//
//D&D Manager, a D&D Character and battle management program.
//Copyright (C) 2007, Matthew Hutton
//
//This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License along with this program; if not, write to:
//The Free Software Foundation, Inc.,
//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

#import "MyDocument.h"
#import "AppController.h"
#import "AbilityChanged.h"
#import "FeatActions.h"
#import "SpellMethods.h"
@implementation AppController
-(id)init{
	//if([[[NSDocumentController sharedDocumentController] currentDocument] appController]!=nil){
	//	return [[[NSDocumentController sharedDocumentController] currentDocument] appController];
	//}
	[super init];
	[RandomNumbers reseedRandomNumbers];//so values random
		//value transformers.
	chooseClass=[[[ChooseClass alloc] init] autorelease];
	sToB=[[[ScoreToBonus alloc] init] autorelease];
	toYN=[[[ToYesNo alloc] init] autorelease];
	dexACbonus=[[[DexACBonus alloc] init] autorelease];
	maxRank=[[[MaxRank alloc] init] autorelease];
	goodOrEvil=[[[GoodOrEvil alloc] init] autorelease];
	lasts=[[[LastsOverARound alloc] init] autorelease];
	damT=[[[Damage alloc] init] autorelease];
	attackB=[[[AttackBonus alloc] init] autorelease];
	wType=[[[WeaponType alloc] init] autorelease];
	//gwc=[[[GreyWhiteColour alloc] init] autorelease];
	nrw=[[[NotRangedWeapon alloc] init] autorelease];
	sp=[[[Spells alloc] init] autorelease];
	ac=[[[ArmourClass alloc] init] autorelease];
	strWeapBonus=[[[StrengthWeaponBonus alloc] init] autorelease];
	n3=[[[NotThree alloc] init] autorelease];
	abilityAttackBonus=[[[AbilityAttackBonus alloc] init] autorelease];
	lvlOrHD=[[[LevelOrHD alloc] init] autorelease];
	[NSValueTransformer setValueTransformer:chooseClass
									forName:@"ChooseClass"];
	[NSValueTransformer setValueTransformer:sToB
									forName:@"ScoreToBonus"];
	[NSValueTransformer setValueTransformer:toYN
									forName:@"ToYesNo"];
	[NSValueTransformer setValueTransformer:dexACbonus
									forName:@"DexACBonus"];
	[NSValueTransformer setValueTransformer:maxRank
									forName:@"MaxRank"];
	[NSValueTransformer setValueTransformer:goodOrEvil
									forName:@"GoodOrEvil"];
	[NSValueTransformer setValueTransformer:lasts
									forName:@"LastsOverARound"];
	[NSValueTransformer setValueTransformer:damT
									forName:@"Damage"];
	[NSValueTransformer setValueTransformer:attackB
									forName:@"AttackBonus"];
	[NSValueTransformer setValueTransformer:wType
									forName:@"WeaponType"];
	//[NSValueTransformer setValueTransformer:gwc
	//								forName:@"GreyWhiteColour"];
	[NSValueTransformer setValueTransformer:nrw
									forName:@"NotRangedWeapon"];
	[NSValueTransformer setValueTransformer:sp
									forName:@"Spells"];
	[NSValueTransformer setValueTransformer:ac
									forName:@"ArmourClass"];
	[NSValueTransformer setValueTransformer:strWeapBonus
									forName:@"StrengthWeaponBonus"];
	[NSValueTransformer setValueTransformer:n3
									forName:@"NotThree"];
	[NSValueTransformer setValueTransformer:abilityAttackBonus
									forName:@"AbilityAttackBonus"];
	[NSValueTransformer setValueTransformer:lvlOrHD
									forName:@"LevelOrHD"];
	//[[[NSDocumentController sharedDocumentController] currentDocument] setManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
	/*int i;
	for(i=0;i<100;i++){
		NSLog(@"random #%d=%d",i,[RandomNumbers randomInt]);
	}*/
	menuController=(MenuController *)[NSApp delegate];
	postModelSetupDone=NO;
	return self;
}
-(void)awakeFromNib{
	[characterController setFilterPredicate:nil];
	[characterController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																								 ascending:YES]]];
	[mainPartyController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																								 ascending:YES]]];
	[enemyPartyController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																								  ascending:YES]]];
	[weaponController setFilterPredicate:nil];
	[weaponController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																							  ascending:YES]]];
	[featsController setFilterPredicate:nil];
	[featsController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																							 ascending:YES]]];
	[skillsController setFilterPredicate:nil];
	[skillsController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																							 ascending:YES]]];
	[spellController setFilterPredicate:nil];
	[spellController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																								 ascending:YES]]];
	[skillsToChooseTable reloadData];
	[characterClassController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																									  ascending:YES]]];
}

-(IBAction)characterSearchUnderway:(id)sender{
	[self characterStuffNeedsSettingUp];
}

-(NSArrayController *)characterController{
	return characterController;
}
-(BattleController *)battleController{
	return battleController;
}
#pragma mark -
#pragma mark Abilities Changed
#pragma mark 
-(IBAction)strengthChanged:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	//set up skills
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged strengthChangedForChar:obj];
	//if([[skillsController arrangedObjects] count]!=0){
	//	[skillsController setSelectionIndex:[skillsController selectionIndex]];
	//}
}
-(IBAction)dexterityChanged:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	//Sets all dexterity based stuff (init,reflex and AC)
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged dexterityChangedForChar:obj];
	[acDexterity setIntValue:[AbilityChanged dexACBonus:obj]];
}
-(IBAction)constitutionChanged:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged constitutionChangedForChar:obj];
	//done afterwards because constitution hp bonus has to be worked out here in AppController to get whether the level is limited to 20.
	[obj setValue:[NSNumber numberWithInt:[self conHPBonusForCharacter:obj]]
		   forKey:@"conBonusHP"];
	[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"conBonusHP"] intValue]+[[obj valueForKey:@"baseHP"] intValue]]
		   forKey:@"maxHP"];
	//if([[skillsController arrangedObjects] count]!=0){
	//	[skillsController setSelectionIndex:[skillsController selectionIndex]];
	//}
}
-(IBAction)intelligenceChanged:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged intelligenceChangedForChar:obj];
}
-(IBAction)wisdomChanged:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	//set up will saving throws
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged wisdomChangedForChar:obj];
}
-(IBAction)charismaChanged:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged charismaChangedForChar:obj];
}
-(int)conHPBonusForCharacter:(NSManagedObject *)obj{
	return [AbilityChanged conHPBonusForCharacter:obj
								bonusLimitedToL20:[[battleStore valueForKey:@"limitConBonus"] boolValue]];
}
-(IBAction)setupArmourClassFromQuick:(id)sender{
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	int total=[[obj valueForKey:@"armourClassTotal"] intValue];
	int touch=[[obj valueForKey:@"armourClassTouch"] intValue];
	int flat=[[obj valueForKey:@"armourClassFlat"] intValue];
	//armour bonus
	[obj setValue:[NSNumber numberWithInt:total-touch]
		   forKey:@"armourClassArmour"];
	//dexterity.
	int dexCheck=total-flat;
	int dexBonus=[AbilityChanged scoreToBonus:[obj valueForKey:@"dexterity"]];
	//if the dex value is bigger than the dex bonus then theres dodge.
	if(dexCheck>dexBonus){
		[obj setValue:[NSNumber numberWithInt:dexCheck-dexBonus]
			   forKey:@"armourClassDodge"];
	//otherwise theres max dex ac bonus.
	}else if(dexCheck<dexBonus){
		[obj setValue:[NSString stringWithFormat:@"+%d",dexBonus-dexCheck]
			   forKey:@"maxDexBonus"];
	}
	//now misc bonus.
	int misc=touch+flat-total-[[obj valueForKey:@"sizeMod"] intValue]-10;
	[obj setValue:[NSNumber numberWithInt:misc]
		   forKey:@"armourClassDeflection"];
}
#pragma mark -
#pragma mark Level Stuff
#pragma mark 
-(IBAction)setLevelOrXP:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	//first set the total level
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	if(![[battleStore valueForKey:@"showLevelUpWindow"] boolValue] || [[obj valueForKey:@"template"] boolValue]){
		[self setLevelOrXPForCharacter:obj
				 withGeneralProcessing:YES
				 withFurtherProcessing:NO
							forClassNo:0];
	}else{
		int classNo=0;
		if([sender isEqualTo:level1]){
			classNo=1;
		}else if([sender isEqualTo:level2]){
			classNo=2;
		}else if([sender isEqualTo:level3]){
			classNo=3;
		}
		[self setLevelOrXPForCharacter:obj
				 withGeneralProcessing:YES
				 withFurtherProcessing:YES
							forClassNo:classNo];
	}
}
-(void)setLevelOrXPForCharacter:(NSManagedObject *)obj
		  withGeneralProcessing:(BOOL)general
		  withFurtherProcessing:(BOOL)further
					 forClassNo:(int)classNo{
	//now check level change applied.
	int levelIncrease=0;
	NSManagedObject *characterClass=nil;
	int cLevel=0;
	if(further){
		switch(classNo){
			case 1:
				cLevel=[[obj valueForKey:@"charClassLvl1"] intValue];
				levelIncrease=[level1 intValue]-cLevel;
				[obj setValue:[NSNumber numberWithInt:[level1 intValue]]
					   forKey:@"charClassLvl1"];
				characterClass=[obj valueForKey:@"characterClass1"];
				break;
			case 2:
				cLevel=[[obj valueForKey:@"charClassLvl2"] intValue];
				levelIncrease=[level2 intValue]-cLevel;
				[obj setValue:[NSNumber numberWithInt:[level2 intValue]]
					   forKey:@"charClassLvl2"];
				characterClass=[obj valueForKey:@"characterClass2"];
				break;
			case 3:			cLevel=[[obj valueForKey:@"charClassLvl3"] intValue];
				levelIncrease=[level3 intValue]-cLevel;
				[obj setValue:[NSNumber numberWithInt:[level3 intValue]]
					   forKey:@"charClassLvl3"];
				characterClass=[obj valueForKey:@"characterClass3"];
				break;
			default:
				break;
		}
	}
	if(general){
		[obj setValue:[NSNumber numberWithInt:[self conHPBonusForCharacter:obj]]
			   forKey:@"conBonusHP"];
		[AbilityChanged setLevelOrXPForChar:obj
						  forCharacterClass:characterClass
						  bonusLimitedToL20:[[battleStore valueForKey:@"limitConBonus"] boolValue]];		
	}else{
		//if no general processing assume the clevel is 0.
		levelIncrease=cLevel;
		cLevel=0;
	}
	//we are finished, a level decrease or other unexciting change (or we shouldn't display the window).
	if(levelIncrease<=0 || !further || characterClass==nil){
		return;
	}
	//set up level up blurb.
	[levelUpBlurb setStringValue:[NSString stringWithFormat:@"%@ has added %d levels of the class %@.",[obj valueForKey:@"name"],levelIncrease,[characterClass valueForKey:@"name"]]];
	int i;
	int extraHP=0;
	int diceType=[[battleStore valueForKey:@"autoRollType"] intValue];
	//set extra HP blurb.
	if(diceType==0){
		[extraHPBlurb setStringValue:@"Extra Hit Points are rolled using this file's default rolling scheme (Straight Roll)."];
	}else if(diceType==1){
		[extraHPBlurb setStringValue:@"Extra Hit Points are rolled using this file's default rolling scheme (Best of Two Rolls)."];
	}else{
		[extraHPBlurb setStringValue:@"Extra Hit Points are rolled using this file's default rolling scheme (Roll with Minimum of 50%)."];
	}
	//set values to header.
	levelUpByLevels=levelIncrease;
	levelUpClassNo=classNo;
	for(i=0;i<levelIncrease;i++){
		int rollUpTo=[[characterClass valueForKey:@"sizeOfHD"] intValue];
		if(diceType==0){
			extraHP=extraHP+[RandomNumbers randomIntUpTo:rollUpTo];
		}else if(diceType==1){
			int tempValue1=[RandomNumbers randomIntUpTo:rollUpTo];
			int tempValue2=[RandomNumbers randomIntUpTo:rollUpTo];
			if(tempValue1>tempValue2){
				extraHP=extraHP+tempValue1;
			}else{
				extraHP=extraHP+tempValue2;				
			}
		}else{
			int tempValue=[RandomNumbers randomIntUpTo:rollUpTo];
			if((int)(rollUpTo/2)>tempValue){
				extraHP=extraHP+(int)(rollUpTo/2);
			}else{
				extraHP=extraHP+tempValue;
			}
		}
	}
	//setting newLI for possible limiting to l20 for stuff.
	int newLI=levelIncrease;
	if(cLevel+levelIncrease>20 && [[battleStore valueForKey:@"limitConBonus"] boolValue]){
		if(cLevel>20){
			//no other change can be made.
			newLI=0;
		}else{
			//set current increase to 20 - the current level.
			newLI=20-cLevel;
		}
	}
	int conBonus=newLI*[AbilityChanged scoreToBonus:[obj valueForKey:@"constitution"]];
	[levelUpConBonusTF setIntValue:conBonus];
	if(conBonus+extraHP<1){
		extraHP=1-conBonus;
	}
	[extraHPTF setIntValue:extraHP];
	[levelUpTotalTF setIntValue:extraHP+conBonus];
	//now setup skill points.
	int noOfSkillPoints=0;
	int noOfSkillPointsPerLevel=[AbilityChanged scoreToBonus:[obj valueForKey:@"intelligence"]]+[[obj valueForKey:@"skillPointsMiscBonus"] intValue]+[[characterClass valueForKey:@"skillPointsPerLevel"] intValue];
	if(cLevel==0 && classNo==1){
		noOfSkillPoints=noOfSkillPointsPerLevel*4+(levelIncrease-1)*noOfSkillPointsPerLevel;
	}else{
		noOfSkillPoints=levelIncrease*noOfSkillPointsPerLevel;
	}
	[levelUpSkillPoints setIntValue:noOfSkillPoints];
	//now setup number of feats.
	int newFeats=0;
	int newLevel=levelIncrease+cLevel;
	if(cLevel==0){
		newFeats=newFeats+[[obj valueForKey:@"noOfMiscFeats"] intValue];
	}
	double baseNo=[[NSUserDefaults standardUserDefaults] floatForKey:@"levelsPerNewFeat"];
	if(baseNo!=0.0){
		newFeats=newFeats+(int)(newLevel/baseNo)-(int)(cLevel/baseNo);
		[levelUpFeatsLabel setStringValue:@"New Feats"];
	}else{
		[levelUpFeatsLabel setStringValue:@"New Bonus Feats"];
	}
	if([[characterClass valueForKey:@"bonusFeatAtLevel1"] boolValue] && cLevel==0){
		newFeats++;
	}
	if([[characterClass valueForKey:@"levelsPerBonusFeat"] intValue]>0){
		int effectiveLevel=newLevel;
		if([[characterClass valueForKey:@"maxLevelOfBonusFeats"] intValue]>0){
			int maxLevel=[[characterClass valueForKey:@"maxLevelOfBonusFeats"] intValue];
			if(effectiveLevel>maxLevel){
				effectiveLevel=maxLevel;
			}
		}
		if(effectiveLevel>cLevel){
			int baseNo2=[[characterClass valueForKey:@"levelsPerBonusFeat"] intValue];
			newFeats=newFeats+(int)(newLevel/baseNo)-(int)(cLevel/baseNo2);
		}
	}
	[levelUpFeats setIntValue:newFeats];
	//now setup no of attacks change.
	if([[obj valueForKey:@"classControlsBaseAttackAndSaves"] boolValue] && [[obj valueForKey:@"usesWeapons"] boolValue]){
		int oldBAB;
		int newBAB;
		if([[characterClass valueForKey:@"baseAttackType"] intValue]==0){
			newBAB=newLI;
			oldBAB=cLevel;
		}else if([[characterClass valueForKey:@"baseAttackType"] intValue]==1){
			newBAB=(int)((newLI*3)/4);
			oldBAB=(int)((cLevel*3)/4);
		}else if([[characterClass valueForKey:@"baseAttackType"] intValue]==2){
			newBAB=(int)(newLI/2);
			oldBAB=(int)(cLevel/2);
		}		
		[levelUpAttack setIntValue:(int)((newBAB-1)/5)-(int)((oldBAB-1)/5)];	
	}else{
		[levelUpAttack setStringValue:@"N/A"];
	}
	//now setup attribute points.
	double baseNoA=[[NSUserDefaults standardUserDefaults] floatForKey:@"levelsPerNewAttributePoint"];
	if(baseNoA!=0.0){
		int newAttr=(int)(newLI/baseNoA)-(int)(cLevel/baseNoA);
		[levelUpAttr setIntValue:newAttr];
		if(newAttr==0){
			[levelUpAttrChooser selectItemAtIndex:0];
			[levelUpAttrChooser setEnabled:NO];
		}else{
			int i;
			int count=[levelUpAttrChooser numberOfItems];
			//remove old items (except "None")
			for(i=2;i<count;i++){
				[levelUpAttrChooser removeItemAtIndex:2];
			}
			//NSLog(@"1");
			//[levelUpAttrChooser removeAllItems];
			//add new titles with scores
			[levelUpAttrChooser addItemsWithTitles:[NSArray arrayWithObjects:[NSString stringWithFormat:@"Strength (now %@)",[obj valueForKey:@"strength"]],[NSString stringWithFormat:@"Dexterity (now %@)",[obj valueForKey:@"dexterity"]],[NSString stringWithFormat:@"Constitution (now %@)",[obj valueForKey:@"constitution"]],[NSString stringWithFormat:@"Intelligence (now %@)",[obj valueForKey:@"intelligence"]],[NSString stringWithFormat:@"Wisdom (now %@)",[obj valueForKey:@"wisdom"]],[NSString stringWithFormat:@"Charisma (now %@)",[obj valueForKey:@"charisma"]],nil]];
			[levelUpAttrChooser setEnabled:YES];
		}
	}else{
		[levelUpAttr setStringValue:@"?"];
		[levelUpAttrChooser setEnabled:NO];
	}
	[NSApp beginSheet:levelUpSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
/*
 * Cancels the level up sheet and changes aren't applied.
 */
-(IBAction)cancelLevelUpSheet:(id)sender{
	[levelUpSheet orderOut:sender];
	[NSApp endSheet:levelUpSheet];
}
/*
 * Continues from the level up sheet and changes are applied.
 */
-(IBAction)closeLevelUpSheet:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	int extraHP=[extraHPTF intValue];
	[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"baseHP"] intValue]+extraHP]
		   forKey:@"baseHP"];
	[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"currentHP"] intValue]+extraHP]
		   forKey:@"currentHP"];
	int extraAttacks=[levelUpAttack intValue];
	[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"noOfAttacks"] intValue]+extraAttacks]
		   forKey:@"noOfAttacks"];
	if([levelUpAttrChooser isEnabled] && ![[levelUpAttrChooser titleOfSelectedItem] isEqualToString:@"No Attribute"]){
		NSString *title=[levelUpAttrChooser titleOfSelectedItem];
		int bonusPoints=[levelUpAttr intValue];
		if([title hasPrefix:@"Strength"]){
			[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"strengthBase"] intValue]+bonusPoints]
				   forKey:@"strengthBase"];
			[AbilityChanged strengthChangedForChar:obj];
		}else if([title hasPrefix:@"Dexterity"]){
			[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"dexterityBase"] intValue]+bonusPoints]
				   forKey:@"dexterityBase"];
			[AbilityChanged dexterityChangedForChar:obj];
		}else if([title hasPrefix:@"Constitution"]){
			[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"constitutionBase"] intValue]+bonusPoints]
				   forKey:@"constitutionBase"];
			[AbilityChanged constitutionChangedForChar:obj];
		}else if([title hasPrefix:@"Intelligence"]){
			[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"intelligenceBase"] intValue]+bonusPoints]
				   forKey:@"intelligenceBase"];
			[AbilityChanged intelligenceChangedForChar:obj];
		}else if([title hasPrefix:@"Wisdom"]){
			[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"wisdomBase"] intValue]+bonusPoints]
				   forKey:@"wisdomBase"];
			[AbilityChanged wisdomChangedForChar:obj];
		}else if([title hasPrefix:@"Charisma"]){
			[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"charismaBase"] intValue]+bonusPoints]
				   forKey:@"charismaBase"];
			[AbilityChanged charismaChangedForChar:obj];
		}
	}
	[AbilityChanged constitutionChangedForChar:obj];
	[levelUpSheet orderOut:sender];
	[NSApp endSheet:levelUpSheet];
}
-(IBAction)autoProcessingCharacterChanged:(id)sender{
	if([sender state]==0){
		[levelUpAttack setStringValue:@"N/A"];
		return;
	}
	int classNo=levelUpClassNo;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *characterClass;
	int newLevel;
	switch(classNo){
		case 1:
			newLevel=[[obj valueForKey:@"charClassLvl1"] intValue];
			characterClass=[obj valueForKey:@"characterClass1"];
			break;
		case 2:
			newLevel=[[obj valueForKey:@"charClassLvl2"] intValue];
			characterClass=[obj valueForKey:@"characterClass2"];
			break;
		case 3:
			newLevel=[[obj valueForKey:@"charClassLvl3"] intValue];
			characterClass=[obj valueForKey:@"characterClass3"];
			break;
		default:
			newLevel=0;
			break;
	}
	int oldLevel=newLevel-levelUpByLevels;
	//now process no of attacks increase as required.
	int oldBAB;
	int newBAB;
	if([[characterClass valueForKey:@"baseAttackType"] intValue]==0){
		newBAB=newLevel;
		oldBAB=oldLevel;
	}else if([[characterClass valueForKey:@"baseAttackType"] intValue]==1){
		newBAB=(int)((newLevel*3)/4);
		oldBAB=(int)((oldLevel*3)/4);
	}else if([[characterClass valueForKey:@"baseAttackType"] intValue]==2){
		newBAB=(int)(newLevel/2);
		oldBAB=(int)(oldLevel/2);
	}		
	[levelUpAttack setIntValue:(int)((newBAB-1)/5)-(int)((oldBAB-1)/5)];
}
-(IBAction)checkLevelUpHP:(id)sender{
	int extraHP=[extraHPTF intValue];
	if(extraHP<1){
		extraHP=1;
	}
	int conBonus=[levelUpConBonusTF intValue];
	if(conBonus+extraHP<1){
		extraHP=1-conBonus;
	}
	[extraHPTF setIntValue:extraHP];
	[levelUpTotalTF setIntValue:extraHP+conBonus];
}
-(IBAction)setupLevelFromQuick:(id)sender{
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	//assumes method comes from the right box, which is the only thing that makes sense...
	[obj setValue:[NSNumber numberWithInt:[sender intValue]]
		   forKey:@"charClassLvl1"];
	//then does other setup.
	[AbilityChanged setLevelOrXPForChar:obj
					  forCharacterClass:[obj valueForKey:@"characterClass1"]
					  bonusLimitedToL20:[[battleStore valueForKey:@"limitConBonus"] boolValue]];
	//[self setupBaseHPQuickForCharacter:obj];
}
#pragma mark -
#pragma mark Random
#pragma mark 
-(int)getCharacterLevelForChar:(NSObject *)obj
					  forClass:(NSString *)theClass{
	if([[obj valueForKey:@"charClassName1"] isEqualToString:theClass]){
		return [[obj valueForKey:@"charClassLvl1"] intValue];
	}else if([[obj valueForKey:@"charClassName2"] isEqualToString:theClass]){
		return [[obj valueForKey:@"charClassLvl2"] intValue];
	}else if([[obj valueForKey:@"charClassName3"] isEqualToString:theClass]){
		return [[obj valueForKey:@"charClassLvl3"] intValue];
	}
	return 0;
}
/*
* Reloads character class options boxes
*/
-(void)reloadDomainOptions{
	[self setupDomainClasses];
}
/*
 *Called by character class boxes, to check whether the old class is a magic caster.
 */
-(IBAction)characterClassChanged:(id)sender{
//check if currently a spell casting class.
	NSString *theClass;
	NSArray *array=[characterController selectedObjects];
	if([array count]==0){
		NSLog(@"no character selected class cannot change (#1).");
		return;
	}
	NSManagedObject *obj=[array objectAtIndex:0];
	NSManagedObject *characterClass;
	int classNo;
	if([sender isEqualTo:charClassNameQuick]){
		[obj setValue:[NSNumber numberWithBool:YES]
			   forKey:@"classControlsBaseAttackAndSaves"];
	}
	[self setupClassControlColorsForCharacter:obj];
	if([sender isEqualTo:charClassName1] || [sender isEqualTo:charClassNameQuick]){
		theClass=[obj valueForKey:@"charClassName1"];
		characterClass=[obj valueForKey:@"characterClass1"];
		classNo=1;
	}else if([sender isEqualTo:charClassName2]){
		theClass=[obj valueForKey:@"charClassName2"];
		characterClass=[obj valueForKey:@"characterClass2"];
		classNo=2;
	}else{
		theClass=[obj valueForKey:@"charClassName3"];
		characterClass=[obj valueForKey:@"characterClass3"];
		classNo=3;
	}
	//NSLog(@"new item=%@",[sender stringValue]);
	NSString *newClass=[sender titleOfSelectedItem];
	NSArray *objects=[[NSArray alloc] initWithObjects:theClass,obj,newClass,[NSNumber numberWithInt:classNo],characterClass,nil];
	if(characterClass!=nil && ![sender isEqualTo:charClassNameQuick]){
		if([[characterClass valueForKey:@"castsSpells"] boolValue] && ![theClass isEqualToString:[sender stringValue]]){
			//old class a magic caster so display sheet about it.
			NSBeginAlertSheet(@"Class Changing", @"Continue", @"Cancel", nil, mainScreen, self,nil,@selector(classChangingDidEnd:returnCode:contextInfo:),objects,@"You are changing the class of this character, and they were a magic caster, all magic setup and spells will be deleted.");
			return;
		}
	}
	//skip to next section.
	[self classChangingDidEnd:nil returnCode:NSAlertDefaultReturn contextInfo:objects];
}
-(void)classChangingDidEnd:(NSWindow *)panel
				returnCode:(int)returnCode
			   contextInfo:(NSArray *)objects{
	//NSLog(@"returnCode=%d",returnCode);
	NSString *theClass=[objects objectAtIndex:0];
	NSManagedObject *obj=[objects objectAtIndex:1];
	NSString *newClass=[objects objectAtIndex:2];
	int classNo=[[objects objectAtIndex:3] intValue];
	NSManagedObject *characterClass=nil;
	if([objects count]==5){
		characterClass=[objects objectAtIndex:4];
	}
	if(returnCode==NSAlertDefaultReturn){
		BOOL oldClassNil=YES;
		if(characterClass!=nil){
			oldClassNil=NO;
			if([[characterClass valueForKey:@"castsSpells"] boolValue]){
				//NSLog(@"removing spellLevels");
				//remove spellLevels for the class
				NSArray *spellLevels=[[[obj valueForKey:@"spellLevel"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"characterClass.name == \"%@\"",theClass]]];// 
				int i;
				for(i=0;i<[spellLevels count];i++){
					[mObjC deleteObject:[spellLevels objectAtIndex:i]];
				}
				//delete all old spells.
				[obj setValue:nil
					   forKey:[NSString stringWithFormat:@"spells%d",classNo]];
			}
		}
		//now check new class exists.
		if(![newClass isEqualToString:@"Choose..."]){
			//NSLog(@"newClass=%@",newClass);
			[characterClassController setFilterPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name==\"%@\"",newClass]]];
			NSArray *array=[characterClassController arrangedObjects];
			if([array count]==0){
				NSLog(@"class not found");
				return;
			}
			NSManagedObject *newCC=[array objectAtIndex:0];
			[obj setValue:newCC
				   forKey:[NSString stringWithFormat:@"characterClass%d",classNo]];
		}else{
			[obj setValue:nil
				   forKey:[NSString stringWithFormat:@"characterClass%d",classNo]];
		}
		[obj setValue:newClass
			   forKey:[NSString stringWithFormat:@"charClassName%d",classNo]];
		//check classes aren't duplicated.
		NSString *class1=[obj valueForKey:@"charClassName1"];
		NSString *class2=[obj valueForKey:@"charClassName2"];
		NSString *class3=[obj valueForKey:@"charClassName3"];
		if([class1 isEqualToString:class2] && ![class1 isEqualToString:@"Choose..."]){
			oldClassNil=NO;//as c1 already processed.
			[obj setValue:@"Choose..."
				   forKey:@"charClassName2"];
			[obj setValue:nil
				   forKey:@"characterClass2"];
			//move level.
			if([[obj valueForKey:@"charClassLvl1"] intValue]==0 && [[obj valueForKey:@"charClassLvl2"] intValue]!=0){
				oldClassNil=NO;
				[obj setValue:[obj valueForKey:@"charClassLvl2"]
					   forKey:@"charClassLvl1"];
				[obj setValue:[NSNumber numberWithInt:0]
					   forKey:@"charClassLvl2"];
				//because level boxes unbound.
				[level2 setIntValue:0];
				[level1 setIntValue:[[obj valueForKey:@"charClassLvl1"] intValue]];
			}
		}
		if([class1 isEqualToString:class3] && ![class1 isEqualToString:@"Choose..."]){
			oldClassNil=NO;//as c1 already processed.
			[obj setValue:@"Choose..."
				   forKey:@"charClassName3"];
			[obj setValue:nil
				   forKey:@"characterClass3"];
			//move level.
			if([[obj valueForKey:@"charClassLvl1"] intValue]==0 && [[obj valueForKey:@"charClassLvl3"] intValue]!=0){
				oldClassNil=NO;
				[obj setValue:[obj valueForKey:@"charClassLvl3"]
					   forKey:@"charClassLvl1"];
				[obj setValue:[NSNumber numberWithInt:0]
					   forKey:@"charClassLvl3"];
				//because level boxes unbound.
				[level3 setIntValue:0];
				[level1 setIntValue:[[obj valueForKey:@"charClassLvl1"] intValue]];
			}
			
		}
		if([class2 isEqualToString:class3] && ![class2 isEqualToString:@"Choose..."]){
			oldClassNil=NO;//as c1 already processed.
			[obj setValue:@"Choose..."
				   forKey:@"charClassName3"];
			[obj setValue:nil
				   forKey:@"characterClass3"];
			//move level.
			if([[obj valueForKey:@"charClassLvl2"] intValue]==0 && [[obj valueForKey:@"charClassLvl3"] intValue]!=0){
				oldClassNil=NO;
				[obj setValue:[obj valueForKey:@"charClassLvl3"]
					   forKey:@"charClassLvl2"];
				[obj setValue:[NSNumber numberWithInt:0]
					   forKey:@"charClassLvl3"];
				//because level boxes unbound.
				[level3 setIntValue:0];
				[level2 setIntValue:[[obj valueForKey:@"charClassLvl2"] intValue]];
			}
		}
		[characterClassController setFilterPredicate:nil];
		[charClassName1 selectItemWithTitle:[obj valueForKey:@"charClassName1"]];
		[charClassName2 selectItemWithTitle:[obj valueForKey:@"charClassName2"]];
		[charClassName3 selectItemWithTitle:[obj valueForKey:@"charClassName3"]];
		if([quickCreateSheet isVisible]){
			//NSLog(@"quick visible");
			[charClassNameQuick selectItemWithTitle:[obj valueForKey:@"charClassName1"]];
			//[self setupBaseHPQuickForCharacter:obj];
		}
		if([AbilityChanged characterTurnsOrRebukesUndead:obj]){
			[turnUndeadOptions setHidden:NO];
			[noTurnUndeadMessage setHidden:YES];
		}else{
			[turnUndeadOptions setHidden:YES];
			[noTurnUndeadMessage setHidden:NO];
		}
		if(oldClassNil && [[battleStore valueForKey:@"showLevelUpWindow"] boolValue] && ![[obj valueForKey:@"template"] boolValue]){
			//old class nil, so check for level up.
			[self setLevelOrXPForCharacter:obj
					 withGeneralProcessing:NO
					 withFurtherProcessing:YES
								forClassNo:classNo];
		}
	}else{
		if(classNo==1){
			[charClassName1 selectItemWithTitle:theClass];
		}else if(classNo==2){
			[charClassName2 selectItemWithTitle:theClass];
		}else{
			[charClassName3 selectItemWithTitle:theClass];
		}
	}
	[objects release];
}
-(IBAction)setupBaseColors:(id)sender{
	if([[characterController selectedObjects] count]==0){
		return;
	}
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[self setupClassControlColorsForCharacter:obj];
	[AbilityChanged setupBaseAttackEtcForCharacter:obj
								 bonusLimitedToL20:[[battleStore valueForKey:@"limitConBonus"] boolValue]];
}
-(void)setupClassControlColorsForCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"classControlsBaseAttackAndSaves"] boolValue]){
		NSColor *grey=[NSColor colorWithDeviceRed:0.93 green:0.93 blue:0.93 alpha:1.0];
		[fortitudeBase setBackgroundColor:grey];
		[fortitudeBase setEditable:NO];
		[reflexBase setBackgroundColor:grey];
		[reflexBase setEditable:NO];
		[willBase setBackgroundColor:grey];
		[willBase setEditable:NO];
		[baseAttackBonus setBackgroundColor:grey];
		[baseAttackBonus setEditable:NO];
		[fortitudeBaseQuick setBackgroundColor:grey];
		[fortitudeBaseQuick setEditable:NO];
		[reflexBaseQuick setBackgroundColor:grey];
		[reflexBaseQuick setEditable:NO];
		[willBaseQuick setBackgroundColor:grey];
		[willBaseQuick setEditable:NO];
		[baseAttackBonusQuick setBackgroundColor:grey];
		[baseAttackBonusQuick setEditable:NO];
	}else{
		[fortitudeBase setBackgroundColor:[NSColor whiteColor]];
		[fortitudeBase setEditable:YES];
		[reflexBase setBackgroundColor:[NSColor whiteColor]];
		[reflexBase setEditable:YES];
		[willBase setBackgroundColor:[NSColor whiteColor]];
		[willBase setEditable:YES];
		[baseAttackBonus setBackgroundColor:[NSColor whiteColor]];
		[baseAttackBonus setEditable:YES];
		[fortitudeBaseQuick setBackgroundColor:[NSColor whiteColor]];
		[fortitudeBaseQuick setEditable:YES];
		[reflexBaseQuick setBackgroundColor:[NSColor whiteColor]];
		[reflexBaseQuick setEditable:YES];
		[willBaseQuick setBackgroundColor:[NSColor whiteColor]];
		[willBaseQuick setEditable:YES];
		[baseAttackBonusQuick setBackgroundColor:[NSColor whiteColor]];
		[baseAttackBonusQuick setEditable:YES];
		
	}
}
-(IBAction)loadQuickSheet:(id)sender{
	if(qpController==nil){
		qpController=[[QuickPrintController alloc] init];
	}
	[qpController displayWindow];
}
/*-(void)setupBaseHPQuickForCharacter:(NSManagedObject *)obj{
	if([obj valueForKey:@"characterClass1"]==nil || [obj valueForKey:@"noOfHD"]==nil || [[obj valueForKey:@"template"] boolValue] || [obj valueForKey:@"baseHP"]!=nil){
		NSLog(@"finished");
		//we are finished, no values chosen (yet), or a template, or the base HP have already been chosen.
		return;
	}
	//assumes level setup.
	NSManagedObject *characterClass=[obj valueForKey:@"characterClass1"];
	int level=[[obj valueForKey:@"level"] intValue];
	int i;
	int extraHP=0;
	int diceType=[[battleStore valueForKey:@"autoRollType"] intValue];
	for(i=0;i<level;i++){
		int rollUpTo=[[characterClass valueForKey:@"sizeOfHD"] intValue];
		if(diceType==0){
			extraHP=extraHP+[RandomNumbers randomIntUpTo:rollUpTo];
		}else if(diceType==1){
			int tempValue1=[RandomNumbers randomIntUpTo:rollUpTo];
			int tempValue2=[RandomNumbers randomIntUpTo:rollUpTo];
			if(tempValue1>tempValue2){
				extraHP=extraHP+tempValue1;
			}else{
				extraHP=extraHP+tempValue2;				
			}
		}else{
			int tempValue=[RandomNumbers randomIntUpTo:rollUpTo];
			if((int)(rollUpTo/2)>tempValue){
				extraHP=extraHP+(int)(rollUpTo/2);
			}else{
				extraHP=extraHP+tempValue;
			}
		}		
	}
	[obj setValue:[NSNumber numberWithInt:extraHP]
		   forKey:@"baseHP"];
	[AbilityChanged constitutionChangedForChar:obj];
}*/
#pragma mark -
#pragma mark Resting
#pragma mark
-(IBAction)loadRestScreen:(id)sender{
	[NSApp beginSheet:restSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
-(IBAction)cancelRestScreen:(id)sender{
	[restSheet orderOut:sender];
	[NSApp endSheet:restSheet];
	[party1Button2 setState:NSOffState];
	[party2Button2 setState:NSOffState];
	[noTemplatesButton2 setState:NSOffState];
	[characterController setFilterPredicate:nil];
}
-(IBAction)restSelectedCharacters:(id)sender{
	[restSheet orderOut:sender];
	[NSApp endSheet:restSheet];
	NSArray *charsToRest=[characterController arrangedObjects];
	BOOL toRestore=[restOrRestore selectedColumn];
	//if not restoring now cast remaining healing spells.
	/*if(!toRestore){
		int g;
		for(g=0;g<[charsToRest count];g++){
			NSManagedObject *obj=[charsToRest objectAtIndex:g];
			int c;
			for(c=1;c<4;c++){
				NSString *theClass=[obj valueForKey:[NSString stringWithFormat:@"charClassName%d",c]];
				NSArray *spellLevels=[[[[obj valueForKey:@"spellLevel"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"charClass MATCHES \"%@\"",theClass]]] sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"level" ascending:YES]]];
				//check if casts spontaneously.
				if([theClass isEqualToString:@"Bard"] || [theClass isEqualToString:@"Sorcerer"] || ([theClass isEqualToString:@"Cleric"] && [[obj valueForKey:@"turnUndead"] boolValue])){
					NSArray *healingSpells=[[[obj valueForKey:[NSString stringWithFormat:@"spells%d",c]] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"type==0"]];
					if([healingSpells count]>0){
						//a healer.
						[self processTheHealingSpells:healingSpells
										 onCharacters:charsToRest
									   byTheCharacter:obj
									forTheClassNumber:c
								   withTheSpellLevels:spellLevels
								 spellsAreSpontaneous:YES];
					}
				}else{
					//check whether any healing spells are memorised.
					int j;
					for(j=0;j<[spellLevels count];j++){
						NSArray *healingSpells=[[[spellLevels valueForKey:@"memorisedSpell"] valueForKey:@"spell"] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"type==0"]];
						if([healingSpells count]>0){
							//a healer
							[self processTheHealingSpells:healingSpells
											 onCharacters:charsToRest
										   byTheCharacter:obj
										forTheClassNumber:c
									   withTheSpellLevels:spellLevels
									 spellsAreSpontaneous:NO];
						}
					}
				}
			}
		}
	}*/
	int i;
	for(i=0;i<[charsToRest count];i++){
		[self restTheCharacter:[charsToRest objectAtIndex:i]
					 toRestore:toRestore];
	}
	[party1Button2 setState:NSOffState];
	[party2Button2 setState:NSOffState];
	[noTemplatesButton2 setState:NSOffState];
	[characterController setFilterPredicate:nil];
}
/*-(void)processTheHealingSpells:(NSArray *)healingSpells
				  onCharacters:(NSArray *)charsToRest
				byTheCharacter:(NSManagedObject *)obj
			 forTheClassNumber:(int)c
			withTheSpellLevels:(NSArray *)spellLevels
		  spellsAreSpontaneous:(BOOL)areSpont{
	NSString *theClass=[obj valueForKey:[NSString stringWithFormat:@"charClassName%d",c]];
	NSString *theClass2=theClass;
	if([theClass isEqualToString:@"Sorcerer"]){
		theClass2=@"Wizard";
	}
	int j;
	for(j=0;j<[healingSpells count];j++){
		NSManagedObject *spell=[healingSpells objectAtIndex:j];
		int spellLevel=[[spell valueForKey:[NSString stringWithFormat:@"level%@",theClass2]] intValue];
		int spellLevel2=spellLevel;
		if([theClass isEqualToString:@"Paladin"] || [theClass isEqualToString:@"Ranger"]){
			spellLevel2--;
		}
		//now check how many casts (if any) we have for the spell.
		int total;
		if(areSpont){
			total=[[[spellLevels objectAtIndex:spellLevel2] valueForKey:@"spellsLeft"] intValue];
			[[spellLevels objectAtIndex:spellLevel2] setValue:[NSNumber numberWithInt:0]
													   forKey:@"spellsLeft"];
		}else{
			total=1;
		}
		int k;
		for(k=0;k<total;k++){
			NSManagedObject *currentSpell=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CurrentSpell"]
												   insertIntoManagedObjectContext:mObjC];
			[currentSpell setValue:obj
							forKey:@"caster"];
			[currentSpell setValue:spell
							forKey:@"spell"];
			[currentSpell setValue:[NSNumber numberWithInt:spellLevel]
							forKey:@"spellLevel"];
			[currentSpell setValue:theClass
							forKey:@"theClassName"];
			[currentSpell setValue:[obj valueForKey:[NSString stringWithFormat:@"charClassLvl%d",c]]
							forKey:@"casterLevel"];
			NSManagedObject *target=[AbilityChanged findTheCharacterWithMostHPLostInTheArray:charsToRest];
			if(target!=nil){
				[battleController processEffectFromCurrentSpell:currentSpell
													   onTarget:target];
			}
		}
	}
}*/
-(void)restTheCharacter:(NSManagedObject *)obj
			  toRestore:(BOOL)restore{
	//check hp and add 1 if character has HP that aren't maximum.
	if([obj valueForKey:@"currentHP"]!=nil &&[obj valueForKey:@"maxHP"]!=nil){
		if([[obj valueForKey:@"currentHP"] intValue]<[[obj valueForKey:@"maxHP"] intValue]){
			if(restore){
				[obj setValue:[obj valueForKey:@"maxHP"]
					   forKey:@"currentHP"];
			}else{
				[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"currentHP"] intValue]+1)]
					   forKey:@"currentHP"];
			}
		}
	}
	//reset turn undead counter.
	[obj setValue:[NSNumber numberWithInt:0]
		   forKey:@"tuTimesUsed"];
	NSArray *spellLevels=[[obj valueForKey:@"spellLevel"] allObjects];
	int j;
	//reset spells.
	for(j=0;j<[spellLevels count];j++){
		NSManagedObject *sl=[spellLevels objectAtIndex:j];
		//get memorised spells as required.
		if([[obj valueForKey:@"memorisesSpells"] boolValue]){
			NSArray *memorisedSpellsA=[[sl valueForKey:@"memorisedSpell"] allObjects];
			int k;
			for(k=0;k<[memorisedSpellsA count];k++){
				[[memorisedSpellsA objectAtIndex:k] setValue:[NSNumber numberWithBool:YES]
													  forKey:@"castable"];
			}
		}
		//reset domain spells
		[sl setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castDomainSpellToday"];
		//reset spells cast counter.
		[sl setValue:[NSNumber numberWithInt:0]
			  forKey:@"spellsCast"];
		[sl setValue:[[spellLevels objectAtIndex:j] valueForKey:@"totalSpells"]
			  forKey:@"spellsLeft"];
	}
	//reset abilities.
	NSArray *abils=[[[obj valueForKey:@"feats"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"ability==1"]];
	for(j=0;j<[abils count];j++){
		NSManagedObject *abil=[abils objectAtIndex:j];
		[abil setValue:[NSNumber numberWithInt:0]
				forKey:@"timesUsedPerDay"];
		[abil setValue:[abil valueForKey:@"usesPerDay"]
				forKey:@"usesLeftPerDay"];
	}
	//reload spell tables.
	if(scController!=nil){
		[scController reloadSpellTables];
	}
}
#pragma mark -
#pragma mark Hasted and Slowed
#pragma mark 
-(IBAction)enableHasted:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	if([sender state]==1){
		[FeatActions enableHastedForChar:obj];
		[slowedButton setEnabled:NO];
	}else{
		[FeatActions disableHastedForChar:obj];
		[slowedButton setEnabled:YES];
	}

}
-(IBAction)enableSlowed:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	if([sender state]==1){
		[FeatActions enableSlowedForChar:obj];
		[hastedButton setEnabled:NO];
	}else{
		[FeatActions disableSlowedForChar:obj];
		[hastedButton setEnabled:YES];
	}	
}
#pragma mark -
#pragma mark Tab Selection
#pragma mark 
-(void)selectBattleTab{
	[mainTabView selectTabViewItemAtIndex:0];
}
-(void)selectCharacterTab{
	[mainTabView selectTabViewItemAtIndex:1];
}
-(void)selectCharacterTesterTab{
	[mainTabView selectTabViewItemAtIndex:2];
}
-(void)selectSpellsTab{
	[mainTabView selectTabViewItemAtIndex:3];
}
-(void)selectDMNotesTab{
	[mainTabView selectTabViewItemAtIndex:4];
}
#pragma mark -
#pragma mark New Character Setup
#pragma mark
-(IBAction)addNewCharacter:(id)sender{
	NSManagedObject *obj=[characterController newObject];
	[characterController addObject:obj];
	[self setupBattleStore];
	[self setupCharacterClasses];
	[self newCharacterSetupForChar:obj];
}
-(IBAction)addNewQuickCharacter:(id)sender{
	NSManagedObject *obj=[characterController newObject];
	[characterController addObject:obj];
	[self setupBattleStore];
	[self setupCharacterClasses];
	[self newCharacterSetupForChar:obj];
	[magicPlusQuick selectItemAtIndex:0];
	[NSApp beginSheet:quickCreateSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
-(void)characterLockNowOn:(BOOL)lockChanged{
	[[[characterController selectedObjects] objectAtIndex:0] setValue:[NSNumber numberWithBool:!lockChanged]
															   forKey:@"canRemove"];
}
/*Runs when a character is locked or unlocked.*/
-(IBAction)characterLockChanged:(id)sender{
	if([[[[characterController selectedObjects] objectAtIndex:0] valueForKey:@"canRemove"] boolValue]){
		[menuController setupCharacterLocked:YES];
		[removeCharacterButton setEnabled:YES];
	}else{
		[menuController setupCharacterLocked:NO];
		[removeCharacterButton setEnabled:NO];
	}
}
/* Sets up new characters */
-(void)newCharacterSetupForChar:(NSManagedObject *)obj{
	//check name
	NSString *name=@"Unnamed character";
	NSArray *array=[[characterController arrangedObjects] valueForKey:@"name"];
	BOOL nameIncluded=NO;
	int i;
	for(i=0;i<[array count];i++){
		if([[array objectAtIndex:i] isEqualToString:name]){
			nameIncluded=YES;
			break;
		}
	}
	if(nameIncluded){
		BOOL goOn=NO;
		int j=2;
		while(!goOn){
			BOOL nameIncluded2=NO;
			int i;
			for(i=0;i<[array count];i++){
				if([[array objectAtIndex:i] isEqualToString:[NSString stringWithFormat:@"%@ #%d",name,j]]){
					nameIncluded2=YES;
					break;
				}
			}
			if(nameIncluded2){
				j++;
			}else{
				[obj setValue:[NSString stringWithFormat:@"%@ #%d",name,j] forKey:@"name"];
				goOn=YES;
				break;
			}
		}
	}
	//Building in Skills (from superskills).
	NSArray *superskills=[[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"superskill" substitutionVariables:[NSDictionary dictionary]] error:nil] sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]]];
	for(i=0;i<[superskills count];i++){
		NSManagedObject *superskill=[superskills objectAtIndex:i];
		if(![[superskill valueForKey:@"useUntrained"] boolValue]){
			continue;
		}
		NSManagedObject *skill=[AbilityChanged createAndSetupSkillFromSuperskill:superskill
																	forCharacter:obj];
		//so listen/search/spot/concentration are locked in as before.
		if([name isEqualToString:@"Spot"] || [name isEqualToString:@"Search"] || [name isEqualToString:@"Listen"] || [name isEqualToString:@"Concentration"]){
			[skill setValue:[NSNumber numberWithBool:NO]
					 forKey:@"canRemove"];
		}
	}
	NSManagedObject *weap=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"Weapon" inManagedObjectContext:mObjC]
								   insertIntoManagedObjectContext:mObjC];
	[weap setValue:@"Unarmed Attack"
			forKey:@"name"];
	[weap setValue:[NSNumber numberWithBool:NO]
			forKey:@"twoHandedWeapon"];
	[weap setValue:[NSNumber numberWithBool:NO]
			forKey:@"canRemove"];
	[weap setValue:@"Bludgeoning"
			forKey:@"damageType"];
	[weap setValue:[NSNumber numberWithInt:3]
			forKey:@"sizeOfDamageDie"];
	[obj setValue:weap
			forKey:@"defaultWeapon"];
	[weap setValue:obj
			forKey:@"character"];
	[obj setValue:weap
			forKey:@"defaultWeapon"];
	[obj setValue:@"Unarmed Attack"
			forKey:@"defaultWeaponForDisp"];
	[weap setValue:[NSNumber numberWithBool:YES]
			forKey:@"defaultWeapon"];
	//generate unique ID
	[obj setValue:[battleStore valueForKey:@"currentUID"]
		   forKey:@"id"];
	[battleStore setValue:[NSNumber numberWithInt:[[battleStore valueForKey:@"currentUID"] intValue]+1]
				   forKey:@"currentUID"];
	[self characterStuffNeedsSettingUp];
}
-(IBAction)closeQuickCharacter:(id)sender{
	[quickCreateSheet orderOut:self];
	[NSApp endSheet:quickCreateSheet];
	if([quickAddToParty1 state]==1){
		[self addToMainParty:nil];
	}
	if([quickAddToParty2 state]==1){
		[self addToEnemyParty:nil];
	}
}
-(IBAction)closeQuickCharacterToSpells:(id)sender{
	[quickCreateSheet orderOut:self];
	[NSApp endSheet:quickCreateSheet];
	[mainTabView selectTabViewItemAtIndex:1];
	[characterTabView selectTabViewItemAtIndex:3];
	if([quickAddToParty1 state]==1){
		[self addToMainParty:nil];
	}
	if([quickAddToParty2 state]==1){
		[self addToEnemyParty:nil];
	}
}
-(IBAction)closeQuickCharacterToAbilities:(id)sender{
	[quickCreateSheet orderOut:self];
	[NSApp endSheet:quickCreateSheet];
	[mainTabView selectTabViewItemAtIndex:1];
	[characterTabView selectTabViewItemAtIndex:4];
	if([quickAddToParty1 state]==1){
		[self addToMainParty:nil];
	}
	if([quickAddToParty2 state]==1){
		[self addToEnemyParty:nil];
	}
}
-(IBAction)cancelQuickCharacter:(id)sender{
	[quickCreateSheet orderOut:self];
	[NSApp endSheet:quickCreateSheet];
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[mObjC deleteObject:obj];
	[characterController rearrangeObjects];
}
#pragma mark -
#pragma mark Battle Setup Actions
#pragma mark 
-(IBAction)addCharBattle:(id)sender{
	[mainTabView selectTabViewItemAtIndex:1];
	[self addNewCharacter:nil];
}
-(IBAction)editCharBattle:(id)sender{
	[mainTabView selectTabViewItemAtIndex:1];
}
//Party Organisation Methods.
-(IBAction)addToMainParty:(id)sender{
	NSArray *selObj;
	selObj=[characterController selectedObjects];
	int i=0;
	for(i;i<[selObj count];i++){
		NSManagedObject *obj=[selObj objectAtIndex:i];
		[self addToMainPartyTheChar:obj];
	}
	[savedPartys1 selectItemWithTitle:@"Custom Party..."];
	if([[enemyPartyController arrangedObjects] count]>0){
		[menuController startNewBattleNowOn:YES];
	}else{
		[menuController startNewBattleNowOn:NO];		
	}
}
-(void)addToMainPartyTheChar:(NSManagedObject *)obj{
	if([[obj class] isEqualTo:[NSManagedObject class]]){
		NSManagedObject *obj2=[self partyAddProcessing:obj];
		[obj2 setValue:[NSNumber numberWithBool:YES]
				forKey:@"mainPartyMember"];
	} else {		
		[NSException raise: NSInternalInconsistencyException
					format: @"Object is not an CharacterMO", [obj class]];		
	}
	if([[obj valueForKey:@"mainPartyMember"] boolValue]){
		[addToMainParty setEnabled:NO];
	}else{
		[addToMainParty setEnabled:YES];
	}
}
-(IBAction)addToEnemyParty:(id)sender{
	NSArray *selObj;
	selObj=[characterController selectedObjects];
	int i=0;
	for(i;i<[selObj count];i++){
		NSManagedObject *obj=[selObj objectAtIndex:i];
		[self addToEnemyPartyTheChar:obj];
	}
	[savedPartys2 selectItemWithTitle:@"Custom Party..."];
	if([[mainPartyController arrangedObjects] count]>0){
		[menuController startNewBattleNowOn:YES];
	}else{
		[menuController startNewBattleNowOn:NO];		
	}
}
-(void)addToEnemyPartyTheChar:(NSManagedObject *)obj{
	if([[obj class] isEqualTo:[NSManagedObject class]]){
		NSManagedObject *obj2=[self partyAddProcessing:obj];
		[obj2 setValue:[NSNumber numberWithBool:YES]
				forKey:@"enemyPartyMember"];
	} else {		
		[NSException raise: NSInternalInconsistencyException
					format: @"Object is not an CharacterMO", [obj class]];		
	}
	if([[obj valueForKey:@"enemyPartyMember"] boolValue]){
		[addToEnemyParty setEnabled:NO];
	}else{
		[addToEnemyParty setEnabled:YES];
	}	
}
-(IBAction)removeFromMainParty:(id)sender{
	NSString *message=@"";
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}
	NSArray *selObj=[mainPartyController selectedObjects];
	int i=0;
	for(i;i<[selObj count];i++){
		NSManagedObject *obj=[selObj objectAtIndex:i];
		[self removeFromMainPartyTheChar:obj
							 withMessage:message];
	}
	if(![message isEqualToString:@""]){
		NSBeginInformationalAlertSheet(@"Event's Result", @"Continue", nil, nil, mainScreen, self,nil,nil,NULL,message);
	}
	[savedPartys1 selectItemWithTitle:@"Custom Party..."];
	[mainPartyController setFilterPredicate:[NSPredicate predicateWithFormat:@"mainPartyMember==1"]];
	if([[mainPartyController arrangedObjects] count]>0){
		[menuController startNewBattleNowOn:YES];
	}else{
		[menuController startNewBattleNowOn:NO];		
	}
}
-(NSString *)removeFromMainPartyTheChar:(NSManagedObject *)obj
							withMessage:(NSString *)message{
	if([[obj class] isEqualTo:[NSManagedObject class]]){
		if([obj valueForKey:@"initiative"]!=nil && ![[obj valueForKey:@"enemyPartyMember"] boolValue]){
			message=[battleController processForExitTheCharacter:obj
													 withMessage:message];
		}
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"mainPartyMember"];
		//check if temporary, as then should delete.
		if([[obj valueForKey:@"temp"] boolValue] && ![[obj valueForKey:@"enemyPartyMember"] boolValue]){
			[mObjC deleteObject:obj];
		}
	}else{
		[NSException raise: NSInternalInconsistencyException
					format: @"Object is not an CharacterMO", [obj class]];		
	}
	if([[characterController selectedObjects] count]>0){
		if([[[[characterController selectedObjects] objectAtIndex:0] valueForKey:@"mainPartyMember"] boolValue]){
			[addToMainParty setEnabled:NO];
		}else{
			[addToMainParty setEnabled:YES];
		}
	}else{
		[addToMainParty setEnabled:NO];
	}
	return message;
}
-(IBAction)removeFromEnemyParty:(id)sender{
	NSString *message=@"";
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}	
	NSArray *selObj;
	selObj=[enemyPartyController selectedObjects];
	int i=0;
	for(i;i<[selObj count];i++){
		NSManagedObject *obj=[selObj objectAtIndex:i];
		[self removeFromEnemyPartyTheChar:obj
							  withMessage:message];
	}
	if(![message isEqualToString:@""]){
		NSBeginInformationalAlertSheet(@"Event's Result", @"Continue", nil, nil, mainScreen, self,nil,nil,NULL,message);
	}
	[savedPartys2 selectItemWithTitle:@"Custom Party..."];
	[enemyPartyController setFilterPredicate:[NSPredicate predicateWithFormat:@"enemyPartyMember==1"]];
	if([[enemyPartyController arrangedObjects] count]>0){
		[menuController startNewBattleNowOn:YES];
	}else{
		[menuController startNewBattleNowOn:NO];		
	}
}
-(NSString *)removeFromEnemyPartyTheChar:(NSManagedObject *)obj
							 withMessage:(NSString *)message{
	if([[obj class] isEqualTo:[NSManagedObject class]]){
		if([obj valueForKey:@"initiative"]!=nil && ![[obj valueForKey:@"mainPartyMember"] boolValue]){
			message=[battleController processForExitTheCharacter:obj
													 withMessage:message];
		}			
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"enemyPartyMember"];
		//check if temporary, as then should delete.
		if([[obj valueForKey:@"temp"] boolValue]  && ![[obj valueForKey:@"mainPartyMember"] boolValue]){
			[mObjC deleteObject:obj];
		}
	} else {		
		[NSException raise: NSInternalInconsistencyException
					format: @"Object is not an CharacterMO", [obj class]];		
	}
	if([[characterController selectedObjects] count]>0){
		if([[[[characterController selectedObjects] objectAtIndex:0] valueForKey:@"enemyPartyMember"] boolValue]){
			[addToEnemyParty setEnabled:NO];
		}else{
			[addToEnemyParty setEnabled:YES];
		}
	}else{
		[addToEnemyParty setEnabled:NO];
	}
	return message;
}
-(NSManagedObject *)partyAddProcessing:(NSManagedObject *)obj{
	if([[obj valueForKey:@"template"] boolValue]){
		NSManagedObject *obj2=[obj duplicate:obj];
		//set up template object r/ship.
		[obj2 setValue:obj
				forKey:@"templateObject"];
		//set up template id.
		[obj2 setValue:[battleStore valueForKey:@"currentTempUID"]
				forKey:@"id"];
		[battleStore setValue:[NSNumber numberWithInt:[[battleStore valueForKey:@"currentTempUID"] intValue]-1]
					   forKey:@"currentTempUID"];
		//set can remove to YES on dups.
		[obj2 setValue:[NSNumber numberWithBool:YES]
				forKey:@"canRemove"];
		//roll hit dice (if possible)
		if(!([obj2 valueForKey:@"noOfHD"]==nil || [obj2 valueForKey:@"sizeOfHD"]==nil)){
			int hp=0;
			int i;
			int diceType=[[battleStore valueForKey:@"tempAutoRollType"] intValue];
			for(i=0;i<[[obj valueForKey:@"noOfHD"] intValue];i++){
				if(diceType==0){
					hp=hp+[RandomNumbers randomIntUpTo:[[obj valueForKey:@"sizeOfHD"] intValue]];
				}else if(diceType==1){
					int temp1=[RandomNumbers randomIntUpTo:[[obj valueForKey:@"sizeOfHD"] intValue]];
					int temp2=[RandomNumbers randomIntUpTo:[[obj valueForKey:@"sizeOfHD"] intValue]];
					if(temp1>temp2){
						hp=hp+temp1;
					}else{
						hp=hp+temp2;						
					}
				}else{
					int rollUpTo=[[obj valueForKey:@"sizeOfHD"] intValue];
					int temp=[RandomNumbers randomIntUpTo:rollUpTo];
					if((int)(rollUpTo/2)>temp){
						hp=hp+(int)(rollUpTo/2);
					}else{
						hp=hp+temp;
					}					
				}
				hp=hp+[AbilityChanged scoreToBonus:[obj valueForKey:@"constitution"]];
			}
			[obj2 setValue:[NSNumber numberWithInt:hp]
					forKey:@"baseHP"];
			[AbilityChanged constitutionChangedForChar:obj2];
			[obj2 setValue:[obj2 valueForKey:@"maxHP"]
					forKey:@"currentHP"];
		}else{
			//check has at least 1 HP.
			if([obj valueForKey:@"currentHP"]==nil){
				[obj setValue:[NSNumber numberWithInt:1]
					   forKey:@"currentHP"];
			}
			//check has at least 1 HP.
			if([obj valueForKey:@"maxHP"]==nil){
				[obj setValue:[NSNumber numberWithInt:1]
					   forKey:@"maxHP"];
			}
		}
		[obj2 setValue:[NSNumber numberWithBool:NO]
				forKey:@"template"];
		[obj2 setValue:[NSNumber numberWithBool:YES]
				forKey:@"temp"];
		NSString *objName=[obj valueForKey:@"name"];
		NSString *str=[[characterController filterPredicate] predicateFormat];
		[characterController setFilterPredicate:nil];
		NSArray *characterNames=[[characterController arrangedObjects] valueForKey:@"name"];
		int i=0;
		//an infinite loop, though as there are only a finite number of characters the loop cannot continue forever.
		while(1==1){
			i++;
			if(![characterNames containsObject:[NSString stringWithFormat:@"%@ #%d",objName,i]]){
				break;
			}
		}
		[obj2 setValue:[NSString stringWithFormat:@"%@ #%d",objName,i]
				forKey:@"name"];
		[characterController setFilterPredicate:[NSPredicate predicateWithFormat:str]];
		[characterController addObject:obj2];
		[characterController rearrangeObjects];
		int row=[[characterController arrangedObjects] indexOfObject:obj];
		[characterTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
		return obj2;
	}else{
		//check has at least 1 HP.
		if([obj valueForKey:@"currentHP"]==nil){
			[obj setValue:[NSNumber numberWithInt:1]
				   forKey:@"currentHP"];
		}
		//check has at least 1 HP.
		if([obj valueForKey:@"maxHP"]==nil){
			[obj setValue:[NSNumber numberWithInt:1]
				   forKey:@"maxHP"];
		}
		return obj;
	}
	return nil;
}
-(IBAction)removeCharacter:(id)sender{
	[characterController setAutomaticallyPreparesContent:YES];
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[characterController removeObject:obj];
	[mObjC deleteObject:obj];
	[self characterStuffNeedsSettingUp];
}
-(IBAction)duplicateCharacter:(id)sender{
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *obj2=[obj duplicate:obj];
	NSString *objName=[obj valueForKey:@"name"];
	NSString *str=[[characterController filterPredicate] predicateFormat];
	[characterController setFilterPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name BEGINSWITH \"%@ #\"",objName]]];
	int c=[[characterController arrangedObjects] count];
	[obj2 setValue:[NSString stringWithFormat:@"%@ #%d",objName,c+1]
			forKey:@"name"];
	[obj2 setValue:[battleStore valueForKey:@"currentUID"]
			forKey:@"id"];
	[battleStore setValue:[NSNumber numberWithInt:[[battleStore valueForKey:@"currentUID"] intValue]+1]
				   forKey:@"currentUID"];
	[characterController addObject:obj2];
	[characterController setFilterPredicate:[NSPredicate predicateWithFormat:str]];
	[characterController rearrangeObjects];
	[characterController setAutomaticallyPreparesContent:NO];
	[characterController prepareContent];
	[characterController setAutomaticallyPreparesContent:YES];
	int row=[[characterController arrangedObjects] indexOfObject:obj2];
	[characterTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
}
-(IBAction)displayRollDiceSheet:(id)sender{
	if(diceController==nil){
		diceController=[[DiceRollerController alloc] init];
	}
	if([mainScreen isVisible] && [mainScreen isKeyWindow]){
		[NSApp beginSheet:[diceController window]
		   modalForWindow:mainScreen
			modalDelegate:self
		   didEndSelector:nil
			  contextInfo:NULL];
	}else{
		[[diceController window] makeKeyAndOrderFront:self];
	}
	//[mainOffController displayRollDiceSheet];
}

-(IBAction)displayGrantXPsheet:(id)sender{
	if(grantXPController==nil){
		grantXPController=[[GrantXPController alloc] initWithCharacterController:characterController
																  withMainWindow:mainScreen];
	}
	[NSApp beginSheet:[grantXPController window]
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
-(IBAction)displayEditCharacterClassesSheet:(id)sender{
	[self setupCharacterClasses];
	if(ccController==nil){
		ccController=[[CharacterClassController alloc] init];
	}
	[[mainScreen toolbar] setSelectedItemIdentifier:@"ClassesTB"];
	NSTabViewItem *tabViewItem=[mainTabView tabViewItemAtIndex:5];
	[tabViewItem setView:[ccController ccView]];
	[mainTabView selectTabViewItem:tabViewItem];
}
-(IBAction)displayWeaponsSheet:(id)sender{
	if(weapController==nil){
		weapController=[[WeaponController alloc] init];
	}
	NSTabViewItem *tabViewItem=[mainTabView tabViewItemAtIndex:6];
	[tabViewItem setView:[weapController weaponView]];
	[mainTabView selectTabViewItem:tabViewItem];
}
-(IBAction)startBattle:(id)sender{
	//check if Battle Controller exists.
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}
	[battleController battleNewSet];
}
-(IBAction)continueBattle:(id)sender{
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}
	[battleController battleContinueSet];
}
-(IBAction)exitBattle:(id)sender{
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}
	[battleController exitBattleMode:nil];
}
#pragma mark -
#pragma mark Character Parties
#pragma mark 
-(void)setupCharacterParties{
	NSRange range;
	range.location=0;
	range.length=[savedPartys1 numberOfItems]-2;
	NSSet *newTitles=[NSSet setWithArray:[[partyController arrangedObjects] valueForKey:@"name"]];
	NSMutableSet *currentTitles=[NSMutableSet setWithCapacity:1];
	if(range.length>0){
		[currentTitles addObjectsFromArray:[[savedPartys1 itemTitles] subarrayWithRange:range]];
	}
	//to add set setup.
	NSMutableSet *toAddTitles=[NSMutableSet setWithCapacity:[newTitles count]];
	[toAddTitles setSet:newTitles];
	[toAddTitles minusSet:currentTitles];
	//to remove set setup.
	[currentTitles minusSet:newTitles];
	//now process to remove.
	NSArray *array=[currentTitles allObjects];
	int i;
	for(i=0;i<[array count];i++){
		[savedPartys1 removeItemWithTitle:[array objectAtIndex:i]];
		[savedPartys2 removeItemWithTitle:[array objectAtIndex:i]];

	}
	//now process to add.
	array=[toAddTitles allObjects];
	int countNow=[savedPartys1 numberOfItems]-2;
	for(i=0;i<[array count];i++){
		[savedPartys1 insertItemWithTitle:[array objectAtIndex:i] atIndex:countNow+i];
		[savedPartys2 insertItemWithTitle:[array objectAtIndex:i] atIndex:countNow+i];
	}
	//now check what is selected.
	if([[savedPartys1 titleOfSelectedItem] isEqualToString:@""]){
		[savedPartys1 selectItemWithTitle:@"Custom Party..."];
		[deleteParty1 setEnabled:NO];
		[renameParty1 setEnabled:NO];
	}
	if([[savedPartys2 titleOfSelectedItem] isEqualToString:@""]){
		[savedPartys2 selectItemWithTitle:@"Custom Party..."];
		[deleteParty2 setEnabled:NO];
		[renameParty2 setEnabled:NO];
	}
}
-(IBAction)renameParty1:(id)sender{
	NSString *theName=[savedPartys1 titleOfSelectedItem];
	NSArray *array=[[partyController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name==\"%@\"",theName]]];
	if([array count]>0){
		[renameTF setStringValue:[[array objectAtIndex:0] valueForKey:@"name"]];
		[renameTypeTF setIntValue:-1];
		[NSApp beginSheet:renameSheet
		   modalForWindow:mainScreen
			modalDelegate:self
		   didEndSelector:@selector(renameSheetDidEnd:returnCode:contextInfo:)
			  contextInfo:[array objectAtIndex:0]];
	}else{
		NSBeep();
		NSLog(@"no such party found, cannot rename.");
	}
		
}
-(IBAction)renameParty2:(id)sender{
	NSString *theName=[savedPartys2 titleOfSelectedItem];
	NSArray *array=[[partyController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name==\"%@\"",theName]]];
	if([array count]>0){
		[renameTF setStringValue:[[array objectAtIndex:0] valueForKey:@"name"]];
		[renameTypeTF setIntValue:-2];
		[NSApp beginSheet:renameSheet
		   modalForWindow:mainScreen
			modalDelegate:self
		   didEndSelector:@selector(renameSheetDidEnd:returnCode:contextInfo:)
			  contextInfo:[array objectAtIndex:0]];
	}else{
		NSBeep();
		NSLog(@"no such party found, cannot rename.");
	}
}
-(IBAction)renameSheetOKd:(id)sender{
	[renameSheet orderOut:self];
	[NSApp endSheet:renameSheet returnCode:0];
}
-(IBAction)renameSheetCancelled:(id)sender{
	[renameSheet orderOut:self];
	[NSApp endSheet:renameSheet returnCode:1];
}
-(void)renameSheetDidEnd:(NSWindow *)panel
			  returnCode:(int)returnCode
			 contextInfo:(NSManagedObject *)party{
	if(returnCode==0){//name changed.
		//get the party.
		int i;
		NSString *theNewName=[renameTF stringValue];
		NSArray *existingChars=[partyController arrangedObjects];
		for(i=0;i<[existingChars count];i++){
			NSString *oldName=[[existingChars objectAtIndex:i] valueForKey:@"name"];
			if(![[existingChars objectAtIndex:i] isEqualTo:party]){
				if([oldName isEqualToString:theNewName]){
					[mObjC deleteObject:[existingChars objectAtIndex:i]];
				}
			}
		}
		[party setValue:theNewName
				 forKey:@"name"];
		if([renameTypeTF intValue]<0){
			[self setupCharacterParties];
			if([renameTypeTF intValue]==-1){
				[savedPartys1 selectItemWithTitle:[renameTF stringValue]];
				[deleteParty1 setEnabled:YES];
				[renameParty1 setEnabled:YES];
			}else{
				[savedPartys2 selectItemWithTitle:[renameTF stringValue]];
				[deleteParty2 setEnabled:YES];
				[renameParty2 setEnabled:YES];
			}
		}else if([renameTypeTF intValue]==0){
			[self saveAsAPartyWithMain:NO
						  withNewParty:party];
			[deleteParty2 setEnabled:YES];
			[renameParty2 setEnabled:YES];
		}else{
			[self saveAsAPartyWithMain:YES
						  withNewParty:party];
			[deleteParty1 setEnabled:YES];
			[renameParty1 setEnabled:YES];
		}
	}else{
		if([renameTypeTF intValue]>-1){
			[mObjC deleteObject:party];
			[self setupCharacterParties];
		}
	}
}
-(IBAction)saveAsAParty1:(id)sender{
	[renameTypeTF setIntValue:1];
	[renameTF setStringValue:@"Unnamed party"];
	[NSApp beginSheet:renameSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:@selector(renameSheetDidEnd:returnCode:contextInfo:)
		  contextInfo:[partyController newObject]];
}
-(IBAction)saveAsAParty2:(id)sender{
	[renameTypeTF setIntValue:0];
	[renameTF setStringValue:@"Unnamed party"];
	[NSApp beginSheet:renameSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:@selector(renameSheetDidEnd:returnCode:contextInfo:)
		  contextInfo:[partyController newObject]];
}
-(void)saveAsAPartyWithMain:(BOOL)main
			   withNewParty:(NSManagedObject *)newParty{
	//NSLog(@"saving started");
	NSArray *chars;
	if(main){
		chars=[mainPartyController arrangedObjects];
	}else{
		chars=[enemyPartyController arrangedObjects];
	}
	NSMutableArray *templates=[NSMutableArray arrayWithCapacity:2];
	int i;
	//NSLog(@"save 1");
	for(i=0;i<[chars count];i++){
		NSManagedObject *obj=[chars objectAtIndex:i];
		if(![[obj valueForKey:@"temp"] boolValue]){
			//a normal character.
			NSManagedObject *partyIntermediate=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"PartyIntermediate" inManagedObjectContext:mObjC] insertIntoManagedObjectContext:mObjC];
			[partyIntermediate setValue:obj
								 forKey:@"character"];
			[partyIntermediate setValue:newParty
								 forKey:@"party"];
		}else if([obj valueForKey:@"templateObject"]!=nil){
			//get the template.
			NSManagedObject *template=[obj valueForKey:@"templateObject"];
			if(![templates containsObject:template]){
				int countOfObjs;
				if(main){
					countOfObjs=[[[[template valueForKey:@"tempObject"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"mainPartyMember==1"]] count];
				}else{
					countOfObjs=[[[[template valueForKey:@"tempObject"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"enemyPartyMember==1"]] count];
				}
				NSManagedObject *partyIntermediate=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"PartyIntermediate" inManagedObjectContext:mObjC] insertIntoManagedObjectContext:mObjC];
				[partyIntermediate setValue:template
									 forKey:@"character"];
				[partyIntermediate setValue:newParty
									 forKey:@"party"];
				[partyIntermediate setValue:[NSNumber numberWithInt:countOfObjs]
									 forKey:@"noOfCopies"];
				[templates addObject:template];
			}
		}
	}
	//NSLog(@"save 2");
	[partyController addObject:newParty];
	NSString *theTitle=[newParty valueForKey:@"name"];
	if(main){
		NSString *otherTitle=[savedPartys2 titleOfSelectedItem];
		[self setupCharacterParties];
		[savedPartys1 selectItemWithTitle:theTitle];
		[savedPartys2 selectItemWithTitle:otherTitle];
	}else{
		NSString *otherTitle=[savedPartys1 titleOfSelectedItem];
		[self setupCharacterParties];
		[savedPartys2 selectItemWithTitle:theTitle];
		[savedPartys1 selectItemWithTitle:otherTitle];
	}
}
-(IBAction)deleteParty1:(id)sender{
	NSString *theName=[savedPartys1 titleOfSelectedItem];
	NSArray *array=[[partyController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name==\"%@\"",theName]]];
	if([array count]>0){
		[partyController removeObject:[array objectAtIndex:0]];
		[mObjC deleteObject:[array objectAtIndex:0]];
		[partyController rearrangeObjects];
		[self setupCharacterParties];
	}else{
		NSLog(@"no party found cannot delete (party 1 box)");
		[partyController rearrangeObjects];
		[self setupCharacterParties];
		NSBeep();
	}
}
-(IBAction)deleteParty2:(id)sender{
	NSString *theName=[savedPartys2 titleOfSelectedItem];
	NSArray *array=[[partyController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name==\"%@\"",theName]]];
	if([array count]>0){
		[partyController removeObject:[array objectAtIndex:0]];
		[mObjC deleteObject:[array objectAtIndex:0]];
		[partyController rearrangeObjects];
		[self setupCharacterParties];
	}else{
		NSLog(@"no party found cannot delete (party 2 box)");
		[partyController rearrangeObjects];
		[self setupCharacterParties];
		NSBeep();
	}
}
-(IBAction)chooseForParty1:(id)sender{
	[self chooseForPartyThatIsMain:YES];
}
-(IBAction)chooseForParty2:(id)sender{
	[self chooseForPartyThatIsMain:NO];
}
-(void)chooseForPartyThatIsMain:(BOOL)main{
	//NSLog(@"choosing");
	NSString *theName;
	if(main){
		theName=[savedPartys1 titleOfSelectedItem];
		if([[savedPartys1 titleOfSelectedItem] isEqualTo:@"Custom Party..."]){
			[deleteParty1 setEnabled:NO];
			[renameParty1 setEnabled:NO];
			return;
		}else{
			[deleteParty1 setEnabled:YES];
			[renameParty1 setEnabled:YES];
		}
	}else{
		theName=[savedPartys2 titleOfSelectedItem];
		if([[savedPartys2 titleOfSelectedItem] isEqualTo:@"Custom Party..."]){
			[deleteParty2 setEnabled:NO];
			[renameParty2 setEnabled:NO];
			return;
		}else{
			[deleteParty2 setEnabled:YES];
			[renameParty2 setEnabled:YES];
		}
	}
	//NSLog(@"c1");
	NSArray *currentChars;
	if(main && [[mainPartyController arrangedObjects] count]>0){
		currentChars=[mainPartyController arrangedObjects];
	}else if(!main && [[enemyPartyController arrangedObjects] count]>0){
		currentChars=[enemyPartyController arrangedObjects];
	}else{
		currentChars=[NSArray array];
	}
	NSArray *array=[[partyController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name==\"%@\"",theName]]];
	if([array count]==0){
		NSBeep();
		//NSLog(@"party doesn't exist so cannot be chosen");
		[partyController rearrangeObjects];
		[self setupCharacterParties];
		return;
	}
	NSManagedObject *party=[array objectAtIndex:0];
	NSArray *newIntermediates=[[party valueForKey:@"character"] allObjects];
	NSArray *newChars=[newIntermediates valueForKey:@"character"];
	//remove oldies.
	int i;
	NSString *message=@"";
	for(i=0;i<[currentChars count];i++){
		NSManagedObject *obj=[currentChars objectAtIndex:i];
		if([[obj valueForKey:@"temp"] boolValue]){
			if(![newChars containsObject:[obj valueForKey:@"templateObject"]]){
				if(main){
					message=[self removeFromMainPartyTheChar:obj
												 withMessage:message];
				}else{
					message=[self removeFromEnemyPartyTheChar:obj
												  withMessage:message];
				}
			}
		}else if(![newChars containsObject:obj]){
			//remove it.
			if(main){
				message=[self removeFromMainPartyTheChar:obj
											 withMessage:message];
			}else{
				message=[self removeFromEnemyPartyTheChar:obj
											  withMessage:message];
			}
		}
	}
	//NSLog(@"c3");
	//add new characters.
	for(i=0;i<[newChars count];i++){
		//NSLog(@"3.0");
		NSManagedObject *obj=[newChars objectAtIndex:i];
		if([[obj valueForKey:@"template"] boolValue]){
			//NSLog(@"c3.1");
			int numberWeShouldHave=[[[newIntermediates objectAtIndex:i] valueForKey:@"noOfCopies"] intValue];
			//check how many temps belonging to it already exist.
			if(main){
				//NSLog(@"c3.2.1");
				NSArray *temps=[[[[obj valueForKey:@"tempObject"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"mainPartyMember==1"]] sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]]];
				int tempsCount=[temps count];\
					int j;
				if(tempsCount<numberWeShouldHave){
					//NSLog(@"3.2.2");
					for(j=0;j<numberWeShouldHave-tempsCount;j++){
						[self addToMainPartyTheChar:obj];
					}
				}else if(tempsCount>numberWeShouldHave){
					//NSLog(@"3.2.3");
					for(j=0;j<numberWeShouldHave-tempsCount;j++){
						[self removeFromMainPartyTheChar:[temps objectAtIndex:j]
											 withMessage:message];
					}
				}
			}else{
				//NSLog(@"3.3.1");
				NSArray *temps=[[[[obj valueForKey:@"tempObject"] allObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"enemyPartyMember==1"]] sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]]];
				int tempsCount=[temps count];\
					int j;
				if(tempsCount<numberWeShouldHave){
					//NSLog(@"3.3.2");
					for(j=0;j<numberWeShouldHave-tempsCount;j++){
						[self addToEnemyPartyTheChar:obj];
					}
				}else if(tempsCount>numberWeShouldHave){
					//NSLog(@"3.3.3");
					for(j=0;j<numberWeShouldHave-tempsCount;j++){
						[self removeFromEnemyPartyTheChar:[temps objectAtIndex:j]
											 withMessage:message];
					}
				}
			}
		}else if(![currentChars containsObject:obj]){
			if(main){
				//NSLog(@"3.4");
				[self addToMainPartyTheChar:obj];
			}else{
				//NSLog(@"3.5");
				[self addToEnemyPartyTheChar:obj];
			}
		}
	}
	//display message if need.
	if(![message isEqualToString:@""]){
		NSBeginInformationalAlertSheet(@"Event's Result", @"Continue", nil, nil, mainScreen, self,nil,nil,NULL,message);
	}
	//NSLog(@"c4");
}
#pragma mark -
#pragma mark Weapons
#pragma mark 
-(void)updateDefaultWeapon{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[defaultWeaponBox setStringValue:[AbilityChanged updateDefaultWeaponForChar:obj]];
}

-(IBAction)lightWeaponsChanged:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[weaponController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	if([sender state]==0){//state off
		if([[weap valueForKey:@"offWeapon"] boolValue]){
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
				   forKey:@"mainHandPenalty"];
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
				   forKey:@"offHandPenalty"];
		}
	}else{//state on.
		if([[weap valueForKey:@"offWeapon"] boolValue]){
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]+2)]
				   forKey:@"mainHandPenalty"];
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]+2)]
				   forKey:@"offHandPenalty"];
		}
	}
	[strWeapField setIntValue:[[strWeapBonus transformedValue:weap] intValue]];
}
-(IBAction)setDefaultWeapon:(id)sender{
	//[defaultWeaponController setFilterPredicate:[NSPredicate predicateWithFormat:@"defaultWeapon == 1"]];
	if([[characterController selectedObjects] count]==0 || [[weaponController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *newWeap=[[weaponController selectedObjects] objectAtIndex:0];
	[AbilityChanged setDefaultWeaponForChar:obj
								 withWeapon:newWeap];
	[self weaponABChangedInCode];
}
-(IBAction)setOffHandWeapon:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[weaponController selectedObjects] count]==0)
		return;
	NSManagedObject *newWeap=[[weaponController selectedObjects] objectAtIndex:0];
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged setOffHandWeaponForChar:obj
								 withWeapon:newWeap];
	[self weaponABChangedInCode];
}
-(IBAction)cancelOffHandWeapon:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged cancelOffHandWeaponForChar:obj];
	[self weaponABChangedInCode];
}
-(IBAction)addNewWeapon:(id)sender{
	NSArray *weapArray;
	weapArray=[weaponController arrangedObjects];
	NSManagedObject *weap=[weaponController newObject];
	//set up attack bonus/str damage as required.
	[weap setValue:[NSNumber numberWithInt:0]
			forKey:@"weaponType"];
	[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"weaponAttackBonus"] intValue]+[[abilityAttackBonus transformedValue:weap] intValue]]
			forKey:@"attackBonus"];
	//set up feats (as required).
	NSArray *array=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"activeWeaponFeat" substitutionVariables:[NSDictionary dictionary]]
										error:nil];
	if([array count]!=0){
		int i;
		NSArray *array2=[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponTypeAffected==2 OR weaponTypeAffected==3"]];
		for(i=0;i<[array2 count];i++){
			NSManagedObject *feat=[array2 objectAtIndex:i];
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:array2
							forwards:YES];
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:array2
							forwards:YES];
		}
	}	
	//now add the object.
	if([weapArray count]==0){
		NSManagedObject *obj=[weap valueForKey:@"character"];
		[obj setValue:weap
			   forKey:@"defaultWeapon"];
		[weaponController addObject:weap];
		//Bodge
		int i=[weaponController selectionIndex];
		[weaponController setSelectionIndex:i];
	}else{
		[weaponController addObject:weap];
	}
}
-(IBAction)removeWeapon:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[weaponController selectedObjects] count]==0 || [[weaponController arrangedObjects] count]==0)
		return;
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	//check for feats tied to weapon.
	/*NSArray *feats=[[weap valueForKey:@"feat"] allObjects];
	int i;
	for(i=0;i<[feats count];i++){
		
	}*/
	[weaponController removeObject:weap];
	[mObjC deleteObject:weap];
	if([[obj valueForKey:@"defaultWeapon"] isEqualTo:weap]){
		NSManagedObject *newWeap=[[weaponController arrangedObjects] objectAtIndex:0];
		[obj setValue:newWeap
			   forKey:@"defaultWeapon"];
		[newWeap setValue:[NSNumber numberWithBool:YES]
				   forKey:@"defaultWeapon"];
		[self updateDefaultWeapon];
	}else if([[obj valueForKey:@"offWeapon"] isEqualTo:weap]){
		[obj setValue:nil
			   forKey:@"offWeapon"];
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"usesTwoWeapons"];
		[self updateDefaultWeapon];
	}
}
-(IBAction)weaponHandedChanged:(id)sender{
	if([[weaponController selectedObjects] count]==0)
		return;
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	NSManagedObject *obj=[weap valueForKey:@"character"];
	//check type.
	//check if default weapon and
	if([[obj valueForKey:@"defaultWeapon"] isEqualTo:weap]){
		int x=[acDexterity intValue];//dex bonus.
		int acTot=[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+x+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
		int acFlatVal=[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
		if([[weap valueForKey:@"twoHandedWeapon"] boolValue]){
			//disable shield for AC bonus.
			[weap setValue:[NSNumber numberWithBool:NO]
				   forKey:@"withShield"];
			[obj setValue:[NSNumber numberWithInt:(acTot-[[obj valueForKey:@"armourClassShield"] intValue])]
				   forKey:@"armourClassTotal"];
			[obj setValue:[NSNumber numberWithInt:(acFlatVal-[[obj valueForKey:@"armourClassShield"] intValue])]
				   forKey:@"armourClassFlat"];
			//disable off hand weapon.
			[self updateDefaultWeapon];
		}
	}
	//check weapon str display.
	if([[weaponController selectedObjects] count]==0)
		return;
	[strWeapField setIntValue:[[strWeapBonus transformedValue:weap] intValue]];
}
-(IBAction)weaponABChanged:(id)sender{
	if([[weaponController selectedObjects] count]==0){
		return;
	}
	[self weaponABChangedInCode];
}
-(void)weaponABChangedInCode{
	if([[weaponController selectedObjects] count]==0){
		return;
	}
	//update text box.
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	[attackBonusTF setIntValue:[[abilityAttackBonus transformedValue:weap] intValue]];//for other uses
	[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"weaponAttackBonus"] intValue]+[[abilityAttackBonus transformedValue:weap] intValue]]
			forKey:@"attackBonus"];
	[strWeapField setIntValue:[[strWeapBonus transformedValue:weap] intValue]];
}
-(IBAction)rangeIncrementSet:(id)sender{
	if([[weaponController selectedObjects] count]==0 || [sender intValue]==0){
		return;
	}
	//update text box.
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	if([[weap valueForKey:@"maxRange"] intValue]==0){
		if([[weap valueForKey:@"weaponType"] intValue]==1){
			[weap setValue:[NSNumber numberWithInt:5*[[weap valueForKey:@"rangeIncrement"] intValue]]
					forKey:@"maxRange"];
		}else{
			[weap setValue:[NSNumber numberWithInt:10*[[weap valueForKey:@"rangeIncrement"] intValue]]
					forKey:@"maxRange"];
		}
	}else if([[weap valueForKey:@"rangeIncrement"] intValue]==0){
		if([[weap valueForKey:@"weaponType"] intValue]==1){
			[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"maxRange"] intValue]/5]
					forKey:@"rangeIncrement"];
		}else{
			[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"maxRange"] intValue]/10]
					forKey:@"rangeIncrement"];
		}
	}
}
-(IBAction)magicWeaponChanged:(id)sender{
	if([[weaponController selectedObjects] count]==0){
		NSLog(@"no weapon selected, so magic weapon can't change.");
		return;
	}
	if(![sender respondsToSelector:@selector(titleOfSelectedItem)]){
		NSLog(@"sender (class %@) doesn't respond to the selector, titleOfSelectedItem, exiting magicWeaponChanged.",[sender class]);
		return;
	}
	NSLog(@"hi");
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	//get old value.
	int oldVal=[[weap valueForKey:@"magicalWeapon"] intValue];
	int newVal=[[sender titleOfSelectedItem] intValue];
	[weap setValue:[NSNumber numberWithInt:newVal]
			forKey:@"magicalWeapon"];
	[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"fixedBonusDamage"] intValue]-oldVal+newVal]
			forKey:@"fixedBonusDamage"];
	[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"weaponAttackBonus"] intValue]-oldVal+newVal]
			forKey:@"weaponAttackBonus"];
}
-(IBAction)quickCriticalChanged:(id)sender{
	if(![sender respondsToSelector:@selector(titleOfSelectedItem)]){
		NSLog(@"error, quickCriticalChanged sender not responding to titleOfSelectedItem");
		return;
	}
	NSArray *weaps=[weaponController selectedObjects];
	if([weaps count]==0){
		NSLog(@"error, no weapon selected in weaponController for quickCriticalChanged");
	}
	NSManagedObject *weap=[weaps objectAtIndex:0];
	NSString *str=[sender titleOfSelectedItem];
	NSRange ran;
	ran.location=0;
	ran.length=2;
	int minValue=[[str substringWithRange:ran] intValue];
	[weap setValue:[NSNumber numberWithInt:minValue]
			forKey:@"minRollForCritical"];
	ran.location=4;
	ran.length=1;
	int multiplier=[[str substringWithRange:ran] intValue];
	[weap setValue:[NSNumber numberWithInt:multiplier]
			forKey:@"criticalMultiplier"];
}
#pragma mark -
#pragma mark Skills
#pragma mark 
-(void)setupSkillsForCharacter:(NSManagedObject *)obj{
	if([[skillsController arrangedObjects] count]!=0){
		NSManagedObject *skill=[[skillsController arrangedObjects] objectAtIndex:[skillTable selectedRow]];
		NSManagedObject *superskill=[skill valueForKey:@"superskill"];
		//set properties.
		[skillNameTF setStringValue:[skill valueForKey:@"name"]];
		int rank=[[skill valueForKey:@"rank"] intValue];
		//NSLog(@"rank=%d",rank);
		[skillRankTF setIntValue:rank];
		[trainedWarning setHidden:YES];
		[skillMiscBonusTF setIntValue:[[skill valueForKey:@"miscBonus"] intValue]];
		[skillAbilityBonusTF setIntValue:[[skill valueForKey:@"abilityBonus"] intValue]];
		[skillTotalTF setIntValue:[[skill valueForKey:@"total"] intValue]];
		
		if([[superskill valueForKey:@"hasKeyAbility"] boolValue]){
			switch([[skill valueForKey:@"ability"] intValue]){
				case 0:
					[relatedAttrTF setStringValue:@"Strength"];
					break;
				case 1:
					[relatedAttrTF setStringValue:@"Intelligence"];
					break;
				case 2:
					[relatedAttrTF setStringValue:@"Dexterity"];
					break;
				case 3:
					[relatedAttrTF setStringValue:@"Wisdom"];
					break;
				case 4:
					[relatedAttrTF setStringValue:@"Constitution"];
					break;
				case 5:
					[relatedAttrTF setStringValue:@"Charisma"];
					break;
				default:
					break;
			}
		}else{
			[relatedAttrTF setStringValue:@"None"];
		}
		if([[skill valueForKey:@"armourCheckApplies"] boolValue]){
			[armourCheckTF setStringValue:@"Yes"];
		}else{
			[armourCheckTF setStringValue:@"No"];
		}
		BOOL aClassExists=NO;
		BOOL classSkill=NO;
		NSSet *characterClasses=[superskill valueForKey:@"classSkillFor"];
		int i;
		for(i=1;i<4;i++){
			NSManagedObject *cc=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
			if(cc!=nil){
				aClassExists=YES;
				if([characterClasses containsObject:cc]){
					classSkill=YES;
				}
			}
		}
		if(aClassExists){
			if(classSkill){
				[crossClassTF setStringValue:@"No"];
				[skill setValue:[NSNumber numberWithBool:NO]
						 forKey:@"crossClass"];
			}else{
				[crossClassTF setStringValue:@"Yes"];
				[skill setValue:[NSNumber numberWithBool:YES]
						 forKey:@"crossClass"];
			}
		}else{
			[crossClassTF setStringValue:@"No"];
			[skill setValue:[NSNumber numberWithBool:NO]
					 forKey:@"crossClass"];
		}
		//check whether name field should be greyed out.
		if(![[skill valueForKey:@"nameEditable"] boolValue]){
			[skillNameTF setEditable:NO];
			[skillNameTF setBackgroundColor:[NSColor colorWithDeviceRed:0.93
																  green:0.93
																   blue:0.93
																  alpha:1.0]];
		}else{
			[skillNameTF setEditable:YES];
			[skillNameTF setBackgroundColor:[NSColor colorWithDeviceRed:1.0
																  green:1.0
																   blue:1.0
																  alpha:1.0]];
		}
	}else{
		//no skills available.
		[trainedWarning setHidden:YES];
		[skillNameTF setEditable:NO];
		[skillNameTF setBackgroundColor:[NSColor colorWithDeviceRed:0.93
															  green:0.93
															   blue:0.93
															  alpha:1.0]];
		
	}
}
-(IBAction)processSkillValues:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[skillsController selectedObjects] count]==0)
		return;
	NSManagedObject *skill=[[skillsController arrangedObjects] objectAtIndex:[skillTable selectedRow]];
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged setupSkillAbilityBonusForSkill:skill
									  forCharacter:obj];
	//NSLog(@"abilNo=%d",abilNo);
	int rank=[skillRankTF intValue];
	int miscBonus=[skillMiscBonusTF intValue];
	if(![[[skill valueForKey:@"superskill"] valueForKey:@"useUntrained"] boolValue] && rank<1){
		[trainedWarning setStringValue:@"Caution, trained only skills must have a rank of at least one."];
		[trainedWarning setHidden:NO];
		rank=1;
		[skillRankTF setIntValue:1];
	}else if(rank<0){
		rank=0;
		[skillRankTF setIntValue:0];
		[trainedWarning setStringValue:@"Caution, untrained skills cannot have a negative rank."];
		[trainedWarning setHidden:NO];
	}else{
		[trainedWarning setHidden:YES];
	}
	[skill setValue:[NSNumber numberWithInt:rank]
			 forKey:@"rank"];
	[skill setValue:[NSNumber numberWithInt:miscBonus]
			 forKey:@"miscBonus"];
	int skillTotal=rank+[[skill valueForKey:@"abilityBonus"] intValue]+miscBonus;
	[skill setValue:[NSNumber numberWithInt:skillTotal]
			   forKey:@"total"];
	[self calculateRemainingSkillPointsForCharacter:obj];
	[skillTable reloadData];
}
-(IBAction)showSuperskillToSkillWindow:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	[globalSkillsTable reloadData];
	[NSApp beginSheet:globalAndCharactersSkillsSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
-(IBAction)miscBonusSkillPointsChanged:(id)sender{
	if([[characterController selectedObjects] count]==0){
		return;
	}
	[self calculateRemainingSkillPointsForCharacter:[[characterController selectedObjects] objectAtIndex:0]];
}
-(void)calculateRemainingSkillPointsForCharacter:(NSManagedObject *)obj{
	int totalSP=0;
	//calculate the total number of skill points for the character.
	int i;
	for(i=1;i<4;i++){
		NSManagedObject *characterClass=[obj valueForKey:[NSString stringWithFormat:@"characterClass%d",i]];
		int level=[[obj valueForKey:[NSString stringWithFormat:@"charClassLvl%d",i]] intValue];
		if(characterClass==nil || level==0){
			continue;
		}
		int noOfSkillPointsPerLevel=[AbilityChanged scoreToBonus:[obj valueForKey:@"intelligence"]]+[[obj valueForKey:@"skillPointsMiscBonus"] intValue]+[[characterClass valueForKey:@"skillPointsPerLevel"] intValue];
		if(i==1){
			totalSP=totalSP+noOfSkillPointsPerLevel*4+(level-1)*noOfSkillPointsPerLevel;
		}else{
			totalSP=totalSP+level*noOfSkillPointsPerLevel;
		}
	}
	//so now we can start taking away the rank of the existing skills.
	NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"crossClass"] boolValue]){
			totalSP=totalSP-2*[[skill valueForKey:@"rank"] intValue];
		}else{
			totalSP=totalSP-[[skill valueForKey:@"rank"] intValue];
		}
	}
	[skillPointsLeftTF setIntValue:totalSP];
}
-(IBAction)testAbility:(id)sender{
	if([[skillsController selectedObjects] count]==0){
		return;
	}
	NSManagedObject *skill=[[skillsController selectedObjects] objectAtIndex:0];
	int dc=[difficultyClass intValue];
	[skill setValue:[AbilityChanged runTestSkill:skill
										   forDC:dc]
			 forKey:@"result"];
}
/*-(IBAction)armourCheckTest:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[skillsController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *skill=[[skillsController selectedObjects] objectAtIndex:0];
	if([armourCheckButton state]==NSOnState){
		if(![[skill valueForKey:@"armourCheckApplies"] boolValue]){
			[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"miscBonus"] intValue]+[[obj valueForKey:@"armourCheckPenalty"] intValue])]
					 forKey:@"miscBonus"];
			[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"total"] intValue]+[[obj valueForKey:@"armourCheckPenalty"] intValue])]
					 forKey:@"total"];
		}
		[skill setValue:[NSNumber numberWithBool:YES]
				 forKey:@"armourCheckApplies"];
	}else{
		if([[skill valueForKey:@"armourCheckApplies"] boolValue]){
			[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"miscBonus"] intValue]-[[obj valueForKey:@"armourCheckPenalty"] intValue])]
					 forKey:@"miscBonus"];
			[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"total"] intValue]-[[obj valueForKey:@"armourCheckPenalty"] intValue])]
					 forKey:@"total"];
		}
		[skill setValue:[NSNumber numberWithBool:NO]
				 forKey:@"armourCheckApplies"];
	}
}*/
-(IBAction)searchCharactersForSkills:(id)sender{
	NSString *searchText=[sender stringValue];
	NSString *filteredPred=[self filterButtonsPred];
	if([searchText isEqualToString:@""] || searchText==nil){
		if([filteredPred isEqualToString:@""]){
			[characterController setFilterPredicate:nil];
		}else{
			[characterController setFilterPredicate:[NSPredicate predicateWithFormat:filteredPred]];
		}
	}else{
		if([filteredPred isEqualToString:@""]){
			[characterController setFilterPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"\"%@\" IN[c] name",searchText]]];
		}else{
			[characterController setFilterPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%@ AND \"%@\" IN[c] name",filteredPred,searchText]]];
		}
	}
}
-(IBAction)testCharacters:(id)sender{
	NSString *pred=[[characterController filterPredicate] predicateFormat];
	//clear existing results.
	[characterController setFilterPredicate:nil];
	NSArray *allChars=[characterController arrangedObjects];
	int i;
	for(i=0;i<[allChars count];i++){
		[[allChars objectAtIndex:i] setValue:@""
									  forKey:@"saveResult"];
	}
	[characterController setFilterPredicate:[NSPredicate predicateWithFormat:pred]];
	//run test
	int row=[skillsToChooseTable selectedRow];
	int dc=[stDifficultyClassBox intValue];
	NSString *testedItem=[self tableView:skillsToChooseTable
			   objectValueForTableColumn:[[skillsToChooseTable tableColumns] objectAtIndex:0]
									 row:row];
	NSArray *charArray=[characterController arrangedObjects];
	for(i=0;i<[charArray count];i++){
		NSManagedObject *obj=[charArray objectAtIndex:i];
		if(row<6){
			int bonus=[AbilityChanged scoreToBonus:[obj valueForKey:[testedItem lowercaseString]]];
			[obj setValue:[AbilityChanged runTestWithBonus:bonus
													 forDC:dc]
				   forKey:@"saveResult"];
		}else if(row<9){
			int bonus=[[obj valueForKey:[NSString stringWithFormat:@"%@Total",[testedItem lowercaseString]]] intValue];
			[obj setValue:[AbilityChanged runTestWithBonus:bonus
													 forDC:dc]
				   forKey:@"saveResult"];
		}else{
			NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
			int j;
			NSManagedObject *currentSkill;
			for(j=0;j<[skills count];j++){
				if([[[skills objectAtIndex:j] valueForKey:@"name"] isEqualToString:testedItem]){
					currentSkill=[skills objectAtIndex:j];
					break;
				}
			}
			[obj setValue:[AbilityChanged runTestSkill:currentSkill
												 forDC:dc]
							forKey:@"saveResult"];
		}
	}
}
-(IBAction)showSuperskillSheet:(id)sender{
	if(superskillController==nil){
		superskillController=[[SuperskillController alloc] init];
	}
	[self setupCharacterClasses];
	[superskillController displaySuperskillWindowAttachedToWindow:mainScreen
												   withCharacters:[characterController arrangedObjects]];
}
-(IBAction)removeSkill:(id)sender{
	if([skillTable selectedRow]==-1){
		NSLog(@"no skill selected");
		return;
	}
	NSManagedObject *skill=[[skillsController arrangedObjects] objectAtIndex:[skillTable selectedRow]];
	[skillsController removeObject:skill];
	[mObjC deleteObject:skill];
	[skillTable reloadData];
}
-(IBAction)addToCharacterSkills:(id)sender{
	if([[characterController selectedObjects] count]==0){
		NSLog(@"no character selected cannot add skills to the character.");
		return;
	}
	NSManagedObject *superskill=[[[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"superskill" substitutionVariables:[NSDictionary dictionary]] error:nil] sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]]] objectAtIndex:[globalSkillsTable selectedRow]];
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject*skill=[AbilityChanged createAndSetupSkillFromSuperskill:superskill
															   forCharacter:obj];
	//apply any skill related feats.
	int skillTotal=[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"abilityBonus"] intValue]+[[skill valueForKey:@"miscBonus"] intValue];
	[skill setValue:[NSNumber numberWithInt:skillTotal]
			 forKey:@"total"];
	[self calculateRemainingSkillPointsForCharacter:obj];
	if(![[superskill valueForKey:@"multipleSubskills"] boolValue]){
		[addToCharacterSkillsButton setEnabled:NO];
	}
	[skillsController rearrangeObjects];
}
-(IBAction)closeAddSuperskillSheet:(id)sender{
	[globalAndCharactersSkillsSheet orderOut:self];
	[NSApp endSheet:globalAndCharactersSkillsSheet];
}
#pragma mark -
#pragma mark Random
#pragma mark
-(IBAction)setupFilters:(id)sender{
	//check which button is pressed.
	if([[sender title] isEqualToString:@"Clear"]){
		if([restSheet isVisible]){
			[party1Button2 setState:NSOffState];
			[party2Button2 setState:NSOffState];
			[noTemplatesButton2 setState:NSOffState];
		}else{
			[party1Button setState:NSOffState];
			[party2Button setState:NSOffState];
			[noTemplatesButton setState:NSOffState];
		}
		[characterController setFilterPredicate:nil];
		int i;
		NSArray *array=[characterController arrangedObjects];
		for(i=0;i<[array count];i++){
			[[array objectAtIndex:i] setValue:@""
									   forKey:@"saveResult"];
		}
	}else{
		NSString *str=[self filterButtonsPred];
		if([str isEqualToString:@""]){
			[characterController setFilterPredicate:nil];
		}else{
			[characterController setFilterPredicate:[NSPredicate predicateWithFormat:str]];
		}
	}
}
-(NSString *)filterButtonsPred{
	NSString *str=@"";
	if(([party1Button state]==NSOnState && ![restSheet isVisible]) ||([party1Button2 state]==NSOnState && [restSheet isVisible])){
		str=@"mainPartyMember==1";
	}
	if(([party2Button state]==NSOnState && ![restSheet isVisible]) ||([party2Button2 state]==NSOnState && [restSheet isVisible])){
		if([str isEqualToString:@""]){
			str=@"enemyPartyMember==1";
		}else{
			if(([andOrToggle state]==0 && ![restSheet isVisible]) || ([andOrToggle2 state]==0 && [restSheet isVisible])){
				str=@"mainPartyMember==1 AND enemyPartyMember==1";
			}else{
				str=@"mainPartyMember==1 OR enemyPartyMember==1";
			}
		}
		
	}
	if(([noTemplatesButton state]==NSOnState && ![restSheet isVisible]) ||([noTemplatesButton state]==NSOnState && [restSheet isVisible])){
		if([str isEqualToString:@""]){
			str=@"template==0";
		}else{
			if([andOrToggle state]==0){
				str=[NSString stringWithFormat:@"%@ AND template==0",str];
			}else{
				str=[NSString stringWithFormat:@"%@ OR template==0",str];
			}
		}
	}
	return str;
}
-(IBAction)runAttackFromMainScreen:(id)sender{
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}
	if([[characterController selectedObjects] count]==0)
		return;
	[battleController runAttackFromMainScreenByCharacter:[[characterController selectedObjects] objectAtIndex:0]];
}
-(IBAction)castSpellFromMainScreen:(id)sender{
	if(battleController==nil){
		battleController=[[BattleController alloc] initWithBattleStore:battleStore
														withMainWindow:mainScreen
											   withCharacterController:characterController];
	}
	if(scController==nil){
		scController=[[SpellClassController alloc] initWithCharController:characterController																				withSpellController:spellController
														  withCharTabView:characterTabView];
	}
	if([[characterController selectedObjects] count]==0)
		return;
	[battleController castSpellFromMainScreenWithCharacter:[[characterController selectedObjects] objectAtIndex:0]
										  withSSController:[scController currentSubview]];
}
-(IBAction)characterMagicScreen:(id)sender{
	[mainTabView selectTabViewItemAtIndex:1];
	[characterTabView selectTabViewItemAtIndex:3];
}
#pragma mark -
#pragma mark Character Portrait
#pragma mark 
//portrait
-(void)openPanelDidEnd:(NSOpenPanel *)panel
			returnCode:(int)returnCode
		   contextInfo:(void *)x{
	if(returnCode==NSOKButton){
		if([[characterController selectedObjects] count]==0){
			NSLog(@"cannot add portrait, no character selected.");
			return;
		}
		NSString *path=[panel filename];
		NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
		//copy the image to ~/Library/Application Support/Quest CoreData.
		NSFileManager *nsfm=[NSFileManager defaultManager];
		NSManagedObject *portrait=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"Portrait"]
										   insertIntoManagedObjectContext:mObjC];
		[portrait setValue:[nsfm contentsAtPath:path]
					forKey:@"portraitData"];
		[obj setValue:portrait
			   forKey:@"portraitObject"];
	}
}
-(IBAction)loadPortrait:(id)sender{
	NSOpenPanel *panel=[NSOpenPanel openPanel];
	[panel beginSheetForDirectory:nil
							 file:nil
							types:[NSImage imageFileTypes]
				   modalForWindow:mainScreen
					modalDelegate:self
				   didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
					  contextInfo:NULL];
}
#pragma mark -
#pragma mark Turn Undead
#pragma mark 
-(IBAction)updateTurnUndead:(id)sender{
	if([[characterController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged updateTurnUndeadForChar:obj];
}
-(void)updateTurnUndeadForChar:(NSManagedObject *)obj{
	int chaMod=[self scoreToBonus:[obj valueForKey:@"charisma"]];
	[obj setValue:[NSNumber numberWithInt:(3+chaMod+[[obj valueForKey:@"tuMiscBonus"] intValue])]
		   forKey:@"tuTotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuCMiscBonus"] intValue])]
		   forKey:@"tuCtotal"];
	
}
#pragma mark -
#pragma mark Feats
#pragma mark
-(NSArray *)getFeatsForCharacter:(NSManagedObject *)obj
					   onATarget:(NSManagedObject *)target
		   withFetchRequestNamed:(NSString *)request{
	NSArray *array=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:request  substitutionVariables:[NSDictionary dictionary]]
										error:nil];
	NSMutableArray *results=[[NSMutableArray alloc] initWithCapacity:1];
	[results addObjectsFromArray:[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"character.id==%@ AND featAffects==0",[obj valueForKey:@"id"]]]]];
	NSLog(@"feat1");
	[results addObjectsFromArray:[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"ANY target.id ==%@ AND featAffects==1",[obj valueForKey:@"id"]]]]];
	if(target !=nil){
		[results addObjectsFromArray:[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"character.id==%@ AND ANY target.id==%@ AND featAffects==2",[obj valueForKey:@"id"],[target valueForKey:@"id"]]]]];
		[results addObjectsFromArray:[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"character.id==%@ AND ANY target.id==%@ AND featAffects==2",[target valueForKey:@"id"],[obj valueForKey:@"id"]]]]];
	}
	return results;
}
-(BOOL)mightBeInCombatFeatShouldActivate:(NSManagedObject *)feat{
	if([[battleStore valueForKey:@"continueBattle"] boolValue]){
		return [FeatActions inCombatFeatShouldActivate:feat];
	}else{
		return [FeatActions generallyFeatShouldActivate:feat];
	}
	
}
-(IBAction)activateFeat:(id)sender{
	if([[featsController selectedObjects] count]==0){
		NSLog(@"feats controller has no rows selected.");
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	if([self mightBeInCombatFeatShouldActivate:feat]){
		if(([featActiveButton state]==NSOnState && [abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==1) || ([abilActiveButton state]==NSOnState && [abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==2)){
			[FeatActions activateInCodeTheFeat:feat
						  nowShouldBeOn:YES];
			if([[feat valueForKey:@"character"] valueForKey:@"initiative"]!=nil && ![[feat valueForKey:@"lastsForever"] boolValue]){
				NSManagedObject *ae=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"ActiveFeat"]
											 insertIntoManagedObjectContext:mObjC];
				[ae setValue:feat
					  forKey:@"feat"];
				[ae setValue:[feat valueForKey:@"character"]
					  forKey:@"caster"];
				if([[feat valueForKey:@"runsUntilBattleEnded"] boolValue]){
					[ae setValue:[NSNumber numberWithInt:0]
						  forKey:@"lastsUntilRound"];
				}else{
					[ae setValue:[NSNumber numberWithInt:[[battleStore valueForKey:@"currentRound"] intValue]+[[feat valueForKey:@"timeLastsFor"] intValue]]
						  forKey:@"lastsUntilRound"];
					//NSLog(@"ability dies in round: %@",[ae valueForKey:@"lastsUntilRound"]);
				}
				if(![[feat valueForKey:@"unlimitedUses"] boolValue]){
					[feat setValue:[NSNumber numberWithInt:[[feat valueForKey:@"usesLeftPerDay"] intValue]-1]
							forKey:@"usesLeftPerDay"];
					[feat setValue:[NSNumber numberWithInt:[[feat valueForKey:@"timesUsedPerDay"] intValue]+1]
							forKey:@"timesUsedPerDay"];
				}
			}
		}else{
			[FeatActions activateInCodeTheFeat:feat
						  nowShouldBeOn:NO];
			//check if in a battle.
			if([[feat valueForKey:@"character"] valueForKey:@"initiative"]!=nil){
				if(battleController==nil){
					battleController=[[BattleController alloc] initWithBattleStore:battleStore
																	withMainWindow:mainScreen
														   withCharacterController:characterController];				
				}
			}
			NSArray *array=[[feat valueForKey:@"activeFeat"] allObjects];
			int i;
			NSString *message=@"";
			for(i=0;i<[array count];i++){
				[battleController killTheActiveEvent:[array objectAtIndex:i]
									   withCharacter:[feat valueForKey:@"character"]
										 withMessage:message
											  toExit:YES];
			}
		}
	}else{
		if(([featActiveButton state]==NSOnState && [abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==1) || ([abilActiveButton state]==NSOnState && [abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==2)){
			[feat setValue:[NSNumber numberWithBool:YES]
					forKey:@"active"];
		}else{
			[feat setValue:[NSNumber numberWithBool:NO]
					forKey:@"active"];
		}
	}
}
-(IBAction)featKeyChanged:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[featsController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	NSString *theKey=[sender titleOfSelectedItem];
	//check whether selected value is the skill.
	if([theKey isEqualToString:[[feat valueForKey:@"skill1"] valueForKey:@"name"]] || [theKey isEqualToString:[[feat valueForKey:@"skill2"] valueForKey:@"name"]] || [theKey isEqualToString:[[feat valueForKey:@"skill3"] valueForKey:@"name"]]|| [theKey isEqualToString:[[feat valueForKey:@"skill4"] valueForKey:@"name"]] || [theKey isEqualToString:@"No Skill Chosen"]){
		theKey=@"Choose Skill...";
	}
	//NSLog(@"theKey=%@",theKey);
	if([sender isEqualTo:featWKey1] || [sender isEqualTo:abilWKey1]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:NO];
			[feat setValue:theKey
					forKey:@"weapKey1"];
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:YES];
		}else{
			[feat setValue:theKey
					forKey:@"weapKey1"];
		}
	}else if([sender isEqualTo:featWKey2] || [sender isEqualTo:abilWKey2]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:NO];
			[feat setValue:theKey
					forKey:@"weapKey2"];
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:YES];
		}else{
			[feat setValue:theKey
					forKey:@"weapKey2"];
		}
	}else if([sender isEqualTo:featKey1] || [sender isEqualTo:abilKey1]){
		if([theKey isEqualToString:@"Choose Skill..."]){//load choose skill sheet.
			skillNo=1;
			[NSApp beginSheet:featToSkillSheet
			   modalForWindow:mainScreen
				modalDelegate:self
			   didEndSelector:nil
				  contextInfo:NULL];
		}else{
			if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
				[FeatActions processFeat:feat
								forKeyNo:1
								  onChar:obj
								forwards:NO];
				[feat setValue:theKey
						forKey:@"key1"];
				[FeatActions processFeat:feat
								forKeyNo:1
								  onChar:obj
								forwards:YES];
			}else{
				[feat setValue:theKey
						forKey:@"key1"];
			}
		}
	}else if([sender isEqualTo:featKey2]|| [sender isEqualTo:abilKey2]){
		if([theKey isEqualToString:@"Choose Skill..."]){//load choose skill sheet.
			skillNo=2;
			[NSApp beginSheet:featToSkillSheet
			   modalForWindow:mainScreen
				modalDelegate:self
			   didEndSelector:nil
				  contextInfo:NULL];
		}else{
			if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
				[FeatActions processFeat:feat
								forKeyNo:2
								  onChar:obj
								forwards:NO];
				[feat setValue:theKey
						forKey:@"key2"];
				[FeatActions processFeat:feat
								forKeyNo:2
								  onChar:obj
								forwards:YES];
			}else{
				[feat setValue:theKey
						forKey:@"key2"];
			}
		}
	}else if([sender isEqualTo:featKey3] || [sender isEqualTo:abilKey3]){
		if([theKey isEqualToString:@"Choose Skill..."]){//load choose skill sheet.
			skillNo=3;
			[NSApp beginSheet:featToSkillSheet
			   modalForWindow:mainScreen
				modalDelegate:self
			   didEndSelector:nil
				  contextInfo:NULL];
		}else{
			if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
				[FeatActions processFeat:feat
								forKeyNo:3
								  onChar:obj
								forwards:NO];
				[feat setValue:theKey
						forKey:@"key3"];
				[FeatActions processFeat:feat
								forKeyNo:3
								  onChar:obj
								forwards:YES];
			}else{
				[feat setValue:theKey
						forKey:@"key3"];
			}
		}
	}else if([sender isEqualTo:featKey4] || [sender isEqualTo:abilKey4]){
		if([theKey isEqualToString:@"Choose Skill..."]){//load choose skill sheet.
			skillNo=4;
			[NSApp beginSheet:featToSkillSheet
			   modalForWindow:mainScreen
				modalDelegate:self
			   didEndSelector:nil
				  contextInfo:NULL];
		}else{
			if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
				[FeatActions processFeat:feat
								forKeyNo:4
								  onChar:obj
								forwards:NO];
				[feat setValue:theKey
						forKey:@"key4"];
				[FeatActions processFeat:feat
								forKeyNo:4
								  onChar:obj
								forwards:YES];
			}else{
				[feat setValue:theKey
						forKey:@"key4"];
			}
		}
	}else if([sender isEqualTo:featSpellKey] || [sender isEqualTo:abilSpellKey]){
		if([theKey isEqualToString:@"Cast as Free Action"] || [theKey isEqualToString:@"Cast Silently"] || [theKey isEqualToString:@"Cast Still"]){
			[abilSpellMod setEnabled:NO];
			[featSpellMod setEnabled:NO];
		}else{
			[abilSpellMod setEnabled:YES];
			[featSpellMod setEnabled:YES];
		}
		[feat setValue:theKey
				forKey:@"spellKey"];
	}
	[self configureFromFeatWeaponType:nil];
}
-(IBAction)featModChanged:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[featsController selectedObjects] count]==0)
		return;
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	NSString *theMod=[sender titleOfSelectedItem];
	if([sender isEqualTo:featWMod1] || [sender isEqualTo:abilWMod1]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:NO];
			[feat setValue:theMod
					forKey:@"weapMod1"];
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:YES];
		}else{
			[feat setValue:theMod
					forKey:@"weapMod1"];
		}
	}else if([sender isEqualTo:featWMod2] || [sender isEqualTo:abilWMod2]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:NO];
			[feat setValue:theMod
					forKey:@"weapMod2"];
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:[[obj valueForKey:@"weapons"] allObjects]
							forwards:YES];
		}else{
			[feat setValue:theMod
					forKey:@"weapMod2"];
		}		
	}else if([sender isEqualTo:featMod1] || [sender isEqualTo:abilMod1]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:1
							  onChar:obj
							forwards:NO];
			[feat setValue:theMod
					forKey:@"mod1"];
			[FeatActions processFeat:feat
							forKeyNo:1
							  onChar:obj
							forwards:YES];
		}else{
			[feat setValue:theMod
					forKey:@"mod1"];
		}
	}else if([sender isEqualTo:featMod2] || [sender isEqualTo:abilMod2]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:2
							  onChar:obj
							forwards:NO];
			[feat setValue:theMod
					forKey:@"mod2"];
			[FeatActions processFeat:feat
							forKeyNo:2
							  onChar:obj
							forwards:YES];
		}else{
			[feat setValue:theMod
					forKey:@"mod2"];
		}
	}else if([sender isEqualTo:featMod3] || [sender isEqualTo:abilMod3]){
		if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
			[FeatActions processFeat:feat
							forKeyNo:3
							  onChar:obj
							forwards:NO];
			[feat setValue:theMod
					forKey:@"mod3"];
			[FeatActions processFeat:feat
							forKeyNo:3
							  onChar:obj
							forwards:YES];
		}else{
			[feat setValue:theMod
					forKey:@"mod3"];
		}
	}else if([sender isEqualTo:featMod4] || [sender isEqualTo:abilMod4]){
			if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat]){
				[FeatActions processFeat:feat
								forKeyNo:4
								  onChar:obj
								forwards:NO];
				[feat setValue:theMod
						forKey:@"mod4"];
				[FeatActions processFeat:feat
								forKeyNo:4
								  onChar:obj
								forwards:YES];
			}else{
				[feat setValue:theMod
						forKey:@"mod4"];
			}
	}else if([sender isEqualTo:featSpellMod] || [sender isEqualTo:abilSpellMod]){
		[feat setValue:theMod
				forKey:@"spellMod"];
	}else if([sender isEqualTo:featSpellLevelMod] || [sender isEqualTo:abilSpellLevelMod]){
		[feat setValue:theMod
				forKey:@"spellLevelMod"];
	}
	if([FeatActions xValueInUse:feat]){
		[xModTF setEnabled:YES];
		[xModTF setIntValue:[[feat valueForKey:@"xValue"] intValue]];
		[xModTF setBackgroundColor:[NSColor colorWithDeviceRed:1.0
														 green:1.0
														  blue:1.0
														 alpha:1.0]];
	}else{
		[xModTF setEnabled:NO];
		[xModTF setStringValue:@"N/A"];
		[xModTF setBackgroundColor:[NSColor colorWithDeviceRed:0.93
														 green:0.93
														  blue:0.93
														 alpha:1.0]];
	}
}
-(IBAction)featWeaponWindowToOpen:(id)sender{
	[NSApp beginSheet:featToWeaponSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
-(IBAction)featFeatWindowToOpen:(id)sender{
	if([[featsController selectedObjects] count]==0)
		return;
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	[featsController setFilterPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"ability==1 AND NOT name like \"%@\"",[feat valueForKey:@"name"]]]];
	[NSApp beginSheet:featToFeatSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:@selector(featToFeatPanelEnded:returnCode:contextInfo:)
		  contextInfo:feat];
}
-(IBAction)featSpellWindowToOpen:(id)sender{
	[spellController setFilterPredicate:nil];
	[NSApp beginSheet:featToSpellSheet
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:nil
		  contextInfo:NULL];
}
-(IBAction)featToWeaponLinkSheetEnded:(id)sender{
	if([[featsController selectedObjects] count]==0 || [[weaponController selectedObjects] count]==0)
		return;
	[featToWeaponSheet orderOut:self];
	[NSApp endSheet:featToWeaponSheet];
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
	if([[feat valueForKey:@"active"] boolValue] && [self mightBeInCombatFeatShouldActivate:feat] && [[feat valueForKey:@"weaponTypeAffected"] intValue]==0){
		if([feat valueForKey:@"weapon"]!=nil){
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:[NSArray arrayWithObject:[feat valueForKey:@"weapon"]]
							forwards:NO];
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:[NSArray arrayWithObject:[feat valueForKey:@"weapon"]]
							forwards:NO];
		}
			[feat setValue:weap
					forKey:@"weapon"];
		if([feat valueForKey:@"weapon"]!=nil){
			[FeatActions processFeat:feat
							forKeyNo:1
						   onWeapons:[NSArray arrayWithObject:weap]
							forwards:YES];
			[FeatActions processFeat:feat
							forKeyNo:2
						   onWeapons:[NSArray arrayWithObject:weap]
							forwards:YES];			
		}
	}else{
		[feat setValue:weap
				forKey:@"weapon"];
	}
	[self configureFromFeatWeaponType:nil];
}
-(IBAction)featToSpellLinkSheetEnded:(id)sender{
	if([[spellController selectedObjects] count]==0 || [[featsController selectedObjects] count]==0)
		return;
	[featToSpellSheet orderOut:self];
	[NSApp endSheet:featToSpellSheet];
	NSManagedObject *spell=[[spellController selectedObjects] objectAtIndex:0];
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	[feat setValue:spell
			forKey:@"spell"];
}
-(IBAction)featToFeatLinkSheetEnded:(id)sender{
	[featToFeatSheet orderOut:self];
	[NSApp endSheet:featToFeatSheet];
}
-(void)featToFeatPanelEnded:(NSWindow *)panel
				 returnCode:(int)returnCode
				contextInfo:(NSManagedObject *)feat{
	if([[featsController selectedObjects] count]!=0){
		NSManagedObject *feat2=[[featsController selectedObjects] objectAtIndex:0];
		[feat setValue:feat2
				forKey:@"afterEffects"];
	}
	[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==1"]];
	[featsController setSelectedObjects:[NSArray arrayWithObject:feat]];
}
-(IBAction)featToSkillLinkSheetEnded:(id)sender{
	if([[characterController selectedObjects] count]==0 || [[featsController selectedObjects] count]==0 || [[skillsController selectedObjects] count]==0)
		return;
	[featToSkillSheet orderOut:self];
	[NSApp endSheet:featToSkillSheet];
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	if([self mightBeInCombatFeatShouldActivate:feat]){
		[FeatActions processFeat:feat
						forKeyNo:skillNo
						  onChar:[[characterController selectedObjects] objectAtIndex:0]
						forwards:NO];
	}
	NSManagedObject *skill=[[skillsController selectedObjects] objectAtIndex:0];
	[feat setValue:skill
			forKey:[NSString stringWithFormat:@"skill%d",skillNo]];
	[feat setValue:[skill valueForKey:@"name"]
			forKey:[NSString stringWithFormat:@"key%d",skillNo]];
	//set title of popupbutton.
	if(skillNo==1){
		[featKey1 selectItemAtIndex:1];
		[abilKey1 selectItemAtIndex:1];
	}else if(skillNo==2){
		[featKey2 selectItemAtIndex:1];
		[abilKey2 selectItemAtIndex:1];
	}else if(skillNo==3){
		[featKey3 selectItemAtIndex:1];
		[abilKey3 selectItemAtIndex:1];
	}else if(skillNo==4){
		[featKey4 selectItemAtIndex:1];
		[abilKey4 selectItemAtIndex:1];
	}
	if([self mightBeInCombatFeatShouldActivate:feat]){
		[FeatActions processFeat:feat
						forKeyNo:skillNo
						  onChar:[[characterController selectedObjects] objectAtIndex:0]
						forwards:YES];
	}
}
-(IBAction)featUpdateUsesPerDay:(id)sender{
	if([[featsController selectedObjects] count]==0)
		return;
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	int usesLeft=[[feat valueForKey:@"usesPerDay"] intValue] -[[feat valueForKey:@"timesUsedPerDay"] intValue];
	[featUsesLeft setIntValue:usesLeft];
	[feat setValue:[NSNumber numberWithInt:usesLeft]
			forKey:@"usesLeftPerDay"];
}
-(void)processFeatTable{
	//NSLog(@"hi processing feat table");
	if([featTable numberOfSelectedRows]==0 || [[featsController selectedObjects] count]==0){
		[featWKey1 selectItemWithTitle:@"No Effect"];
		[featWKey2 selectItemWithTitle:@"No Effect"];
		[featWMod1 selectItemWithTitle:@"+0"];
		[featWMod2 selectItemWithTitle:@"+0"];
		[featKey1 selectItemWithTitle:@"No Effect"];
		[featKey2 selectItemWithTitle:@"No Effect"];
		[featKey3 selectItemWithTitle:@"No Effect"];
		[featKey4 selectItemWithTitle:@"No Effect"];
		[featMod1 selectItemWithTitle:@"+0"];
		[featMod2 selectItemWithTitle:@"+0"];
		[featMod3 selectItemWithTitle:@"+0"];
		[featMod4 selectItemWithTitle:@"+0"];
		//disabling buttons when nothing is selected.
		[featWType setEnabled:NO];
		[abilWType setEnabled:NO];
		[featActiveButton setEnabled:NO];
		[featWKey1 setEnabled:NO];
		[featWKey2 setEnabled:NO];
		[featWMod1 setEnabled:NO];
		[featWMod2 setEnabled:NO];
		[featKey1 setEnabled:NO];
		[featKey2 setEnabled:NO];
		[featKey3 setEnabled:NO];
		[featKey4 setEnabled:NO];
		[featMod1 setEnabled:NO];
		[featMod2 setEnabled:NO];
		[featMod3 setEnabled:NO];
		[featMod4 setEnabled:NO];
		[featAffects setEnabled:NO];
		[featSpellKey setEnabled:NO];
		[featSpellMod setEnabled:NO];
		[featSpellLevelMod setEnabled:NO];
		[xModTF setEnabled:NO];
		[xModTF setStringValue:@"No Selection"];
		[abilActiveButton setEnabled:NO];
		[abilWKey1 setEnabled:NO];
		[abilWKey2 setEnabled:NO];
		[abilWMod1 setEnabled:NO];
		[abilWMod2 setEnabled:NO];
		[abilKey1 setEnabled:NO];
		[abilKey2 setEnabled:NO];
		[abilKey3 setEnabled:NO];
		[abilKey4 setEnabled:NO];
		[abilMod1 setEnabled:NO];
		[abilMod2 setEnabled:NO];
		[abilMod3 setEnabled:NO];
		[abilMod4 setEnabled:NO];
		[abilAffects setEnabled:NO];
		[abilFilter setEnabled:NO];
		[abilSpellKey setEnabled:NO];
		[abilSpellMod setEnabled:NO];
		[abilSpellLevelMod setEnabled:NO];
		//max range colours.
		[featMaxRange setEnabled:NO];
		[abilMaxRange setEnabled:NO];
		[featMaxRange setBackgroundColor:[NSColor colorWithDeviceRed:0.93
															   green:0.93
																blue:0.93
															   alpha:1.0]];
		[abilMaxRange setBackgroundColor:[NSColor colorWithDeviceRed:0.93
															   green:0.93
																blue:0.93
															   alpha:1.0]];
		//[featMod1 setEnabled:NO];
	}else{
		//enabling buttons when nothing is selected.
		[featActiveButton setEnabled:YES];
		[featWKey1 setEnabled:YES];
		[featWKey2 setEnabled:YES];
		[featWMod1 setEnabled:YES];
		[featWMod2 setEnabled:YES];
		[featKey1 setEnabled:YES];
		[featKey2 setEnabled:YES];
		[featKey3 setEnabled:YES];
		[featKey4 setEnabled:YES];
		[featMod1 setEnabled:YES];
		[featMod2 setEnabled:YES];
		[featMod3 setEnabled:YES];
		[featMod4 setEnabled:YES];
		[featSpellKey setEnabled:YES];
		[featSpellMod setEnabled:YES];
		[featSpellLevelMod setEnabled:YES];
		[featAffects setEnabled:YES];
		[xModTF setEnabled:YES];
		//[featMod1 setEnabled:YES];
		//NSLog(@"feat table setup");
		NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
		//NSLog(@"done");
		[featType selectItemAtIndex:[[feat valueForKey:@"type"] intValue]];
		[featActiveButton setState:[[feat valueForKey:@"active"] boolValue]];
		[featWKey1 selectItemWithTitle:[feat valueForKey:@"weapKey1"]];
		[featWKey2 selectItemWithTitle:[feat valueForKey:@"weapKey2"]];
		//fix for off penalty.
		if([[feat valueForKey:@"weapKey2"] isEqualToString:@"TW Off Penalty"]){
			[featWKey2 selectItemAtIndex:10];
		}
		if([[feat valueForKey:@"weapKey1"] isEqualToString:@"TW Off Penalty"]){
			[featWKey1 selectItemAtIndex:10];
		}
		//NSLog(@"weapKey2=%@",[feat valueForKey:@"weapKey2"]);
		[featWMod1 selectItemWithTitle:[feat valueForKey:@"weapMod1"]];
		[featWMod2 selectItemWithTitle:[feat valueForKey:@"weapMod2"]];
		[featKey1 selectItemWithTitle:[feat valueForKey:@"key1"]];
		[featKey2 selectItemWithTitle:[feat valueForKey:@"key2"]];
		[featKey3 selectItemWithTitle:[feat valueForKey:@"key3"]];
		[featKey4 selectItemWithTitle:[feat valueForKey:@"key4"]];
		[featMod1 selectItemWithTitle:[feat valueForKey:@"mod1"]];
		[featMod2 selectItemWithTitle:[feat valueForKey:@"mod2"]];
		[featMod3 selectItemWithTitle:[feat valueForKey:@"mod3"]];
		[featMod4 selectItemWithTitle:[feat valueForKey:@"mod4"]];
		[featSpellKey selectItemWithTitle:[feat valueForKey:@"spellKey"]];
		[featSpellMod selectItemWithTitle:[feat valueForKey:@"spellMod"]];
		[featSpellLevelMod selectItemWithTitle:[feat valueForKey:@"spellLevelMod"]];
		[featAffects selectItemAtIndex:[[feat valueForKey:@"featAffects"] intValue]];
		//check if xmod should be active.
		if([FeatActions xValueInUse:feat]){
			[xModTF setEnabled:YES];
			[xModTF setIntValue:[[feat valueForKey:@"xValue"] intValue]];
			[xModTF setBackgroundColor:[NSColor colorWithDeviceRed:1.0
															 green:1.0
															  blue:1.0
															 alpha:1.0]];
		}else{
			[xModTF setEnabled:NO];
			[xModTF setStringValue:@"N/A"];
			[xModTF setBackgroundColor:[NSColor colorWithDeviceRed:0.93
															 green:0.93
															  blue:0.93
															 alpha:1.0]];
		}
		//check color/activity of max range boxes.
		[self configureFromFeatWeaponType:nil];
		[abilActiveButton setEnabled:YES];
		[abilWKey1 setEnabled:YES];
		[abilWKey2 setEnabled:YES];
		[abilWMod1 setEnabled:YES];
		[abilWMod2 setEnabled:YES];
		[abilKey1 setEnabled:YES];
		[abilKey2 setEnabled:YES];
		[abilKey3 setEnabled:YES];
		[abilKey4 setEnabled:YES];
		[abilMod1 setEnabled:YES];
		[abilMod2 setEnabled:YES];
		[abilMod3 setEnabled:YES];
		[abilMod4 setEnabled:YES];
		[abilAffects setEnabled:YES];
		[abilFilter setEnabled:YES];
		[abilSpellKey setEnabled:YES];
		[abilSpellMod setEnabled:YES];
		[abilSpellLevelMod setEnabled:YES];
		//[abilMod1 setEnabled:YES];
		[abilType selectItemAtIndex:[[feat valueForKey:@"type"] intValue]];
		[abilActiveButton setState:[[feat valueForKey:@"active"] boolValue]];
		[abilWKey1 selectItemWithTitle:[feat valueForKey:@"weapKey1"]];
		[abilWKey2 selectItemWithTitle:[feat valueForKey:@"weapKey2"]];
		[abilWMod1 selectItemWithTitle:[feat valueForKey:@"weapMod1"]];
		[abilWMod2 selectItemWithTitle:[feat valueForKey:@"weapMod2"]];
		[abilKey1 selectItemWithTitle:[feat valueForKey:@"key1"]];
		[abilKey2 selectItemWithTitle:[feat valueForKey:@"key2"]];
		[abilKey3 selectItemWithTitle:[feat valueForKey:@"key3"]];
		[abilKey4 selectItemWithTitle:[feat valueForKey:@"key4"]];
		[abilMod1 selectItemWithTitle:[feat valueForKey:@"mod1"]];
		[abilMod2 selectItemWithTitle:[feat valueForKey:@"mod2"]];
		[abilMod3 selectItemWithTitle:[feat valueForKey:@"mod3"]];
		[abilMod4 selectItemWithTitle:[feat valueForKey:@"mod4"]];
		[abilSpellKey selectItemWithTitle:[feat valueForKey:@"spellKey"]];
		[abilSpellMod selectItemWithTitle:[feat valueForKey:@"spellMod"]];
		[abilSpellLevelMod selectItemWithTitle:[feat valueForKey:@"spellLevelMod"]];
		[abilAffects selectItemAtIndex:[[feat valueForKey:@"featAffects"] intValue]];
		[abilFilter selectItemWithTitle:[feat valueForKey:@"featFilter"]];
		if([[feat valueForKey:@"spellKey"] hasPrefix:@"Cast "]){
			[abilSpellMod setEnabled:NO];
			[featSpellMod setEnabled:NO];
		}else{
			[abilSpellMod setEnabled:YES];
			[featSpellMod setEnabled:YES];
		}
	}
}
-(IBAction)configureFromFeatWeaponType:(id)sender{
	if([[featsController selectedObjects] count]==0){
		NSLog(@"no feat selected, from configureFromFeatWeaponType");
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	if([FeatActions generallyFeatShouldActivate:feat] && sender!=nil){
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:NO];
	}
	if([sender isEqualTo:featWType] || [sender isEqualTo:abilWType]){
		[feat setValue:[NSNumber numberWithInt:[sender indexOfSelectedItem]]
				forKey:@"weaponTypeAffected"];
	}
	if([sender isEqualTo:featMaxRange] || [sender isEqualTo:abilMaxRange]){
		[feat setValue:[NSNumber numberWithInt:[sender intValue]]
				forKey:@"maxRange"];
	}
	if([[feat valueForKey:@"weapKey1"] hasSuffix:@"Penalty"] || [[feat valueForKey:@"weapKey2"] hasSuffix:@"Penalty"]){//set type to all weapons, if a Two Weapon Feat.
		[feat setValue:[NSNumber numberWithInt:3]
				forKey:@"weaponTypeAffected"];
		[featWType setEnabled:NO];
		[abilWType setEnabled:NO];
	}else{
		[featWType setEnabled:YES];
		[abilWType setEnabled:YES];
	}
	//check max range box.
	if(([[feat valueForKey:@"weaponTypeAffected"] intValue]==0 && [[[feat valueForKey:@"weapon"] valueForKey:@"weaponType"] intValue]!=0) || [[feat valueForKey:@"weaponTypeAffected"] intValue]==1 || [[feat valueForKey:@"weaponTypeAffected"] intValue]==3){
		[featMaxRange setBackgroundColor:[NSColor colorWithDeviceRed:1.0
															   green:1.0
																blue:1.0
															   alpha:1.0]];
		[abilMaxRange setBackgroundColor:[NSColor colorWithDeviceRed:1.0
															   green:1.0
																blue:1.0
															   alpha:1.0]];
		[featMaxRange setEnabled:YES];
		[abilMaxRange setEnabled:YES];
	}else{
		[featMaxRange setBackgroundColor:[NSColor colorWithDeviceRed:0.93
															   green:0.93
																blue:0.93
															   alpha:1.0]];
		[abilMaxRange setBackgroundColor:[NSColor colorWithDeviceRed:0.93
															   green:0.93
																blue:0.93
															   alpha:1.0]];
		[featMaxRange setEnabled:NO];
		[abilMaxRange setEnabled:NO];
	}
	if([FeatActions generallyFeatShouldActivate:feat]&& sender!=nil){
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:YES];
	}
}
-(IBAction)unlimitedFeatsChanged:(id)sender{
	if([[featsController selectedObjects] count]==0){
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	if([sender state]==1){
		[feat setValue:nil
				forKey:@"usesLeftPerDay"];
		[feat setValue:nil
				forKey:@"usesPerDay"];
		[feat setValue:nil
				forKey:@"timesUsedPerDay"];
	}
}
-(IBAction)addNewFeat:(id)sender{
	NSManagedObject *feat=[featsController newObject];
	[feat setValue:[NSNumber numberWithBool:NO]
			forKey:@"ability"];
	[feat setValue:[NSNumber numberWithBool:YES]
			forKey:@"active"];
	[featActiveButton setState:NSOnState];
	[featsController addObject:feat];
	if([self mightBeInCombatFeatShouldActivate:feat]){
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:YES];
	}
	[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==0"]];
	[featsController setSelectedObjects:[NSArray arrayWithObject:feat]];
}
-(IBAction)addNewAbility:(id)sender{
	NSManagedObject *abil=[featsController newObject];
	[abil setValue:[NSNumber numberWithBool:YES]
			forKey:@"ability"];
	[abil setValue:@"Unnamed Ability"
			forKey:@"name"];
	[abil setValue:[NSNumber numberWithBool:NO]
			forKey:@"lastsForever"];
	[abilActiveButton setState:NSOffState];
	[featsController addObject:abil];
	[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==1"]];
	[featsController setSelectedObjects:[NSArray arrayWithObject:abil]];
}
-(IBAction)xModifierChanged:(id)sender{
	if([[featsController selectedObjects] count]==0){
		NSLog(@"no feat selected, xMod change code cannot run.");
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	if([[feat valueForKey:@"active"] boolValue] && [FeatActions generallyFeatShouldActivate:feat]){
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:NO];
		[feat setValue:[NSNumber numberWithInt:[xModTF intValue]]
				forKey:@"xValue"];
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:YES];
	}else{
		[feat setValue:[NSNumber numberWithInt:[xModTF intValue]]
				forKey:@"xValue"];
	}
}
-(IBAction)featTypeChanged:(id)sender{
	if([[featsController selectedObjects] count]==0){
		NSLog(@"no feat selected, feat type change code cannot run.");
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	BOOL wasActive;
	if([[feat valueForKey:@"active"] boolValue] && [FeatActions generallyFeatShouldActivate:feat]){
		wasActive=YES;
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:NO];
	}
	int newIndex=[sender indexOfSelectedItem];
	[feat setValue:[NSNumber numberWithInt:newIndex]
			forKey:@"type"];
	if(newIndex!=3){
		[feat setValue:nil
				forKey:@"miscUse"];
	}
	if(wasActive && [FeatActions generallyFeatShouldActivate:feat]){
		[FeatActions activateInCodeTheFeat:feat
							 nowShouldBeOn:YES];
	}
}
-(IBAction)featFilterChanged:(id)sender{
	if([[featsController selectedObjects] count]==0){
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	//switch off feat as required.
	if([[feat valueForKey:@"active"] boolValue]){
		if([[feat valueForKey:@"featFilter"] isEqualToString:@"All"]){
			[FeatActions activateInCodeTheFeat:feat
								 nowShouldBeOn:NO];
		}
		//set value.
		[feat setValue:[[sender selectedItem] title]
				forKey:@"featFilter"];
		//switch on feat as required.
		if([[feat valueForKey:@"featFilter"] isEqualToString:@"All"]){
			[FeatActions activateInCodeTheFeat:feat
								 nowShouldBeOn:YES];
		}
	}else{
		[feat setValue:[NSNumber numberWithInt:[sender indexOfSelectedItem]]
				forKey:@"featFilter"];
	}
}
-(IBAction)featAffectsChanged:(id)sender{
	if([[featsController selectedObjects] count]==0){
		return;
	}
	NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
	if([[feat valueForKey:@"active"] boolValue]){
		//switch off feat as required.
		if([[feat valueForKey:@"featAffects"] intValue]==0 || ([[feat valueForKey:@"featAffects"] intValue]==1 && [feat valueForKey:@"target"]!=nil)){
			[FeatActions activateInCodeTheFeat:feat
								 nowShouldBeOn:NO];
			if([[feat valueForKey:@"featAffects"] intValue]==1 && [sender indexOfSelectedItem]!=1){
				//clears targets.
				[feat setValue:nil
						forKey:@"target"];
			}
		}
		//set value.
		[feat setValue:[NSNumber numberWithInt:[sender indexOfSelectedItem]]
				forKey:@"featAffects"];
		//switch on feat as required.
		if([[feat valueForKey:@"featAffects"] intValue]==0 || ([[feat valueForKey:@"featAffects"] intValue]==1 && [feat valueForKey:@"target"]!=nil)){
			[FeatActions activateInCodeTheFeat:feat
								 nowShouldBeOn:YES];
		}
	}else{
		[feat setValue:[NSNumber numberWithInt:[sender indexOfSelectedItem]]
				forKey:@"featAffects"];
	}
}
-(IBAction)setupNoOfFeats:(id)sender{
	if([[characterController selectedObjects] count]==0){
		return;
	}
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	[AbilityChanged getNumberOfFeatsForTheCharacter:obj];
}
#pragma mark -
#pragma mark Immunities
#pragma mark 
-(IBAction)loadImmunitiesPanel:(id)sender{
	//check if sender's window is attached to the mainScreen.
	NSWindow *sendersWindow=[sender window];
	if([[mainScreen attachedSheet] isEqualTo:sendersWindow]){
		[sendersWindow orderOut:self];
		[NSApp endSheet:sendersWindow];
	}else{
		sendersWindow=nil;
	}
	[NSApp beginSheet:immunitiesPanel
	   modalForWindow:mainScreen
		modalDelegate:self
	   didEndSelector:@selector(immunitiesPanelClosed:returnCode:contextInfo:)
		  contextInfo:sendersWindow];
}
-(IBAction)processImmunitiesOptions:(id)sender{
	if([[immunitiesController selectedObjects] count]==0){
		return;
	}
	//check if critical hits or magic weapon or not.
	NSManagedObject *imm=[[immunitiesController selectedObjects] objectAtIndex:0];
	if([[imm valueForKey:@"damageType"] isEqualToString:@"Critical Hits"]){
		[imm setValue:[NSNumber numberWithInt:100]
			   forKey:@"value"];
		[imm setValue:[NSNumber numberWithBool:YES]
			   forKey:@"percentage"];
		[immValueTF setEnabled:NO];
		[immPercentage setEnabled:NO];
		[imm setValue:[NSNumber numberWithBool:NO]
			   forKey:@"vulnerability"];
		[immResistance setEnabled:NO];
	}else if([[imm valueForKey:@"damageType"] isEqualToString:@"Death"]){
		[imm setValue:[NSNumber numberWithInt:100]
			   forKey:@"value"];
		[imm setValue:[NSNumber numberWithBool:YES]
			   forKey:@"percentage"];
		[immValueTF setEnabled:NO];
		[immPercentage setEnabled:NO];
		[imm setValue:[NSNumber numberWithBool:NO]
			   forKey:@"vulnerability"];
		[immResistance setEnabled:NO];
	}else if([[imm valueForKey:@"damageType"] hasSuffix:@"Weapon"]){
		[imm setValue:[NSNumber numberWithBool:NO]
			   forKey:@"percentage"];
		[imm setValue:[NSNumber numberWithBool:NO]
			   forKey:@"vulnerability"];
		[immResistance setEnabled:NO];
		[immPercentage setEnabled:NO];
		[immValueTF setEnabled:YES];
	}else if([[imm valueForKey:@"vulnerability"] boolValue]){//vulnerabilities can't be fixed value.
		[imm setValue:[NSNumber numberWithBool:YES]
			   forKey:@"percentage"];
		[immPercentage setEnabled:NO];
		[immValueTF setEnabled:YES];
	}else{
		[immValueTF setEnabled:YES];
		[immResistance setEnabled:YES];
		[immPercentage setEnabled:YES];
	}
	NSString *type;
	if([[imm valueForKey:@"percentage"] boolValue]){
		type=[NSString stringWithFormat:@"%d%%",[[imm valueForKey:@"value"] intValue]];
	}else{
		type=[NSString stringWithFormat:@"%d",[[imm valueForKey:@"value"] intValue]];
	}
	if([[imm valueForKey:@"vulnerability"] boolValue]){
		if([[imm valueForKey:@"damageType"] isEqualToString:@"Damage Type"]){
			[imm setValue:@"Unknown Vulnerability"
				   forKey:@"name"];
		}else{
			[imm setValue:[NSString stringWithFormat:@"%@ Vulnerability (%@)",[imm valueForKey:@"damageType"],type]
				   forKey:@"name"];
		}
	}else{
		if([[imm valueForKey:@"damageType"] isEqualToString:@"Damage Type"]){
			[imm setValue:@"Unknown Resistance"
				   forKey:@"name"];
		}else{
			[imm setValue:[NSString stringWithFormat:@"%@ Resistance (%@)",[imm valueForKey:@"damageType"],type]
				   forKey:@"name"];
		}
	}
}
-(IBAction)closeImmunitiesPanel:(id)sender{
	[immunitiesPanel orderOut:self];
	[NSApp endSheet:immunitiesPanel];
}
-(void)immunitiesPanelClosed:(NSWindow *)panel
				  returnCode:(int)returnCode
				 contextInfo:(NSWindow *)sendersWindow{
	if(sendersWindow!=nil){
		[NSApp beginSheet:sendersWindow
		   modalForWindow:mainScreen
			modalDelegate:self
		   didEndSelector:nil
			  contextInfo:NULL];
	}
}
- (NSArray*) objectsWithFetchRequest:(NSString*)request matchingPredicate:(NSPredicate*)predicate
{
    NSArray *array=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:request substitutionVariables:[NSDictionary dictionary]]
										error:nil];
	array=[array filteredArrayUsingPredicate:predicate];
	return array;
}
-(NSManagedObject *)createNewManagedObjectForName:(NSString *)str{
	NSManagedObject *obj=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:str]
								  insertIntoManagedObjectContext:mObjC];
	return obj;
}
-(int)scoreToBonus:(NSNumber *)score{
	return [AbilityChanged scoreToBonus:score];
}
+(BOOL)isGood:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasSuffix:@"Good"]){
		return YES;
	}
	return NO;
}
+(BOOL)isEvil:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasSuffix:@"Evil"]){
		return YES;
	}
	return NO;
}
+(BOOL)isLawful:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasPrefix:@"Lawful"]){
		return YES;
	}
	return NO;}
+(BOOL)isChaotic:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasPrefix:@"Chaotic"]){
		return YES;
	}
	return NO;
}
-(void)displayLogSheet{
	if([mainScreen isVisible] && [mainScreen isKeyWindow]){
		[NSApp beginSheet:logSheet
		   modalForWindow:mainScreen
			modalDelegate:self
		   didEndSelector:nil
			  contextInfo:NULL];
	}else{
		//NSLog(@"order forward");
		[logSheet makeKeyAndOrderFront:self];
	}
	//NSLog(@"hello");
}
-(IBAction)closeLogSheet:(id)sender{
	[logSheet orderOut:sender];
	if([mainScreen isVisible]){
		[NSApp endSheet:logSheet];
	}
}
-(IBAction)clearLogSheet:(id)sender{
	[self setupBattleStore];
	[battleStore setValue:[NSString stringWithFormat:@"==%@==",[[NSDate date] description]]
				   forKey:@"eventLog"];
}
-(void)addToLogTheString:(NSString *)theString{
	[self setupBattleStore];
	[battleStore setValue:[[battleStore valueForKey:@"eventLog"] stringByAppendingFormat:@"\n%@",theString]
				   forKey:@"eventLog"];
}
#pragma mark-
#pragma mark Delegate functions
#pragma mark 
-(void)controlTextDidEndEditing:(NSNotification *)aNotification{
	if( [[aNotification object] isEqualTo:weaponNameField] || [[aNotification object] isEqualTo:weaponTableView]){
		[self updateDefaultWeapon];
	}else if([[aNotification object] isEqualTo:armourCheckPenalty]){
		//NSLog(@"armourCheckPenalty changed.");
		NSArray *skills=[skillsController arrangedObjects];
		if([[characterController selectedObjects] count]==0)
			return;
		NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
		int newacp=[armourCheckPenalty intValue];
		int changeACP=newacp-[[obj valueForKey:@"armourCheckPenalty"] intValue];
		int i;
		for(i=0;i<[skills count];i++){
			NSManagedObject *skill=[skills objectAtIndex:i];
			if([[skill valueForKey:@"armourCheckApplies"] boolValue]){
				[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"miscBonus"] intValue]+changeACP)]
						 forKey:@"miscBonus"];
				[skill setValue:[NSNumber numberWithInt:([[skill valueForKey:@"total"] intValue]+changeACP)]
						 forKey:@"total"];
			}
		}
		[obj setValue:[NSNumber numberWithInt:newacp]
			   forKey:@"armourCheckPenalty"];
	}
}
- (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(int)rowIndex{
	return YES;
}
-(void)tableViewSelectionDidChange:(NSNotification *)notification{
	//NSLog(@"app table selection changed.");
	if([[notification object] isEqualTo:weaponTableView]){
		//NSLog(@"weaponTable");
		if([[weaponController selectedObjects] count]!=0){
			[self updateDefaultWeapon];
			//set up attack bonus/str damage as required.
			NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];//the current weapon.
			[strWeapField setIntValue:[[strWeapBonus transformedValue:weap] intValue]];
			[attackBonusTF setIntValue:[[abilityAttackBonus transformedValue:weap] intValue]];
			[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"weaponAttackBonus"] intValue]+[[abilityAttackBonus transformedValue:weap] intValue]]
					forKey:@"attackBonus"];
			[magicPlusMS selectItemAtIndex:[[weap valueForKey:@"magicalWeapon"] intValue]];
		}
	}else if([[notification object] isEqualTo:skillTable]){
		if([[characterController selectedObjects] count]==0){
			NSLog(@"no character available, so skills cannot be setup.");
			return;
		}
		//NSLog(@"skilltable");
		[self setupSkillsForCharacter:[[characterController selectedObjects] objectAtIndex:0]];
	}else if([[notification object] isEqualTo:featTable] || [[notification object] isEqualTo:abilTable]){
		if([[featsController selectedObjects] count]==0){
			return;
		}
		[self processFeatTable];
	}else if([[notification object] isEqualTo:characterTable]){
		//NSLog(@"charactertable");
		if([[characterController selectedObjects] count]==0){
			return;
		}		
		[self characterStuffNeedsSettingUp];
	}else if([[notification object] isEqualTo:characterTableBattle]){
		//NSLog(@"charactertable battle");
		if([[characterController selectedObjects] count]==0){
			[addToMainParty setEnabled:NO];
			[addToEnemyParty setEnabled:NO];
			return;
		}
		NSManagedObject *obj=[[characterController arrangedObjects] objectAtIndex:[characterTableBattle selectedRow]];
		if([[obj valueForKey:@"mainPartyMember"] boolValue]){
			[addToMainParty setEnabled:NO];
		}else{
			[addToMainParty setEnabled:YES];
		}
		if([[obj valueForKey:@"enemyPartyMember"] boolValue]){
			[addToEnemyParty setEnabled:NO];
		}else{
			[addToEnemyParty setEnabled:YES];
		}
	}else if([[notification object] isEqualTo:quickWeaponsTable]){
		NSArray *selWeap=[weaponController selectedObjects];
		if([selWeap count]==0){
			if([quickCreateSheet isVisible]){
				NSLog(@"error, no weapon selected in the quickWeaponsTable");
			}
			return;
		}
		NSManagedObject *weap=[selWeap objectAtIndex:0];
		[magicPlusQuick selectItemAtIndex:[[weap valueForKey:@"magicalWeapon"] intValue]];
		[criticalTypeQuick selectItemWithTitle:[NSString stringWithFormat:@"%d/x%d",[[weap valueForKey:@"minRollForCritical"] intValue],[[weap valueForKey:@"criticalMultiplier"] intValue]]];
	}else if([[notification object] isEqualTo:globalSkillsTable]){
		if([globalSkillsTable selectedRow]==-1 || [[characterController selectedObjects] count]==0){
			return;
		}
		NSManagedObject *superskill=[[[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"superskill" substitutionVariables:[NSDictionary dictionary]] error:nil] sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]]] objectAtIndex:[globalSkillsTable selectedRow]];
		if([[superskill valueForKey:@"multipleSubskills"] boolValue]){
			[addToCharacterSkillsButton setEnabled:YES];
			return;
		}
		NSMutableSet *charactersSkills=[NSMutableSet setWithCapacity:1];
		NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
		[charactersSkills setSet:[obj valueForKey:@"skills"]];
		NSSet *skillsForSuperskill=[superskill valueForKey:@"skill"];
		[charactersSkills intersectSet:skillsForSuperskill];
		if([charactersSkills count]>0){
			[addToCharacterSkillsButton setEnabled:NO];
		}else{
			[addToCharacterSkillsButton setEnabled:YES];
		}
	}
	//NSLog(@"selection changed SO over");
}
- (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem{
	//NSLog(@"app willSelectTabViewItem");
	if([tabView isEqualTo:featTypeStuff]){
		//get the current tab view item.
		if([[featsController selectedObjects] count]==0){
			return;
		}
		NSManagedObject *feat=[[featsController selectedObjects] objectAtIndex:0];
		if([[feat valueForKey:@"active"] boolValue]==NO){
			return;//as no work needs doing.
		}
		NSTabViewItem *currentTab=[tabView selectedTabViewItem];
		if([tabView indexOfTabViewItem:currentTab]==1){
			//used to be a weapon.
			NSArray *weapons=[[weaponController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponType!=1"]];
			int i;
			for(i=0;i<[weapons count];i++){
				NSManagedObject *weap=[weapons objectAtIndex:i];
				[FeatActions processFeat:feat
						 forKeyNo:1
						 onWeapons:[NSArray arrayWithObject:weap]
						 forwards:NO];
				[FeatActions processFeat:feat
						 forKeyNo:2
						 onWeapons:[NSArray arrayWithObject:weap]
						 forwards:NO];
			}
		}else if([tabView indexOfTabViewItem:currentTab]==2){
			if([[characterController selectedObjects] count]==0)
				return;
			NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
			//used to be abilty.
			[FeatActions processFeat:feat
					 forKeyNo:1
					 onChar:obj
					 forwards:NO];
			[FeatActions processFeat:feat
					 forKeyNo:2
					   onChar:obj
					 forwards:NO];
			[FeatActions processFeat:feat
					 forKeyNo:3
					   onChar:obj
					 forwards:NO];
		}
		//process spell feats later.
		//now activate back for new type.
		if([tabView indexOfTabViewItem:tabViewItem]==1){
			//now a weapon.
			NSArray *weapons=[[weaponController arrangedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponType!=1"]];
			[FeatActions processFeat:feat
					 forKeyNo:1
					 onWeapons:weapons
					 forwards:YES];
			[FeatActions processFeat:feat
					 forKeyNo:2
					 onWeapons:weapons
					 forwards:YES];
		}else if([tabView indexOfTabViewItem:tabViewItem]==2){
			if([[characterController selectedObjects] count]==0)
				return;
			NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
			//now an abilty.
			[FeatActions processFeat:feat
					 forKeyNo:1
					   onChar:obj
					 forwards:YES];
			[FeatActions processFeat:feat
					 forKeyNo:2
					   onChar:obj
					 forwards:YES];
			[FeatActions processFeat:feat
					 forKeyNo:3
					   onChar:obj
					 forwards:YES];
		}
		//process spell feats later.
	}else if([tabView isEqualTo:abilitiesTabView]){
		if([abilitiesTabView indexOfTabViewItem:tabViewItem]==1){
			[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==0"]];
			[self processFeatTable];
		}else if([abilitiesTabView indexOfTabViewItem:tabViewItem]==2){
			[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==1"]];
			[self processFeatTable];
		}
	}else if([tabView isEqualTo:mainTabView]){
		if([mainTabView indexOfTabViewItem:[mainTabView selectedTabViewItem]]==2){
			[characterController setFilterPredicate:nil];
		}
		if([mainTabView indexOfTabViewItem:tabViewItem]==0){
			[self setupCharacterParties];
			if([[savedPartys1 titleOfSelectedItem] isEqualTo:@"Custom Party..."]){
				[renameParty1 setEnabled:NO];
				[deleteParty1 setEnabled:NO];
			}else{
				[renameParty1 setEnabled:YES];				
				[deleteParty1 setEnabled:YES];
			}
			if([[savedPartys2 titleOfSelectedItem] isEqualTo:@"Custom Party..."]){
				[renameParty2 setEnabled:NO];
				[deleteParty2 setEnabled:NO];
			}else{
				[renameParty2 setEnabled:YES];
				[deleteParty2 setEnabled:YES];		
			}
		}else if([mainTabView indexOfTabViewItem:tabViewItem]==1){ 
			[self characterStuffNeedsSettingUp];
		}else if([mainTabView indexOfTabViewItem:tabViewItem]==2){
			NSString *str=[self filterButtonsPred];
			if([str isEqualToString:@""]){
				[characterController setFilterPredicate:nil];
			}else{
				[characterController setFilterPredicate:[NSPredicate predicateWithFormat:str]];
			}
		}else if([mainTabView indexOfTabViewItem:tabViewItem]==3){
			[self setupCharacterClasses];
			//if(1==1){
			if(svController==nil){
				svController=[[SpellSVController alloc] init];
			}
			[svController attachMainViewToTabViewItem:tabViewItem];
			[svController setupBattleButtons:[[battleStore valueForKey:@"continueBattle"] boolValue]];
			[svController areaTypeChanged:nil];
			[svController castingTimeChanged:nil];
			[svController savingThrowTypeChanged:nil];
			[svController spellAffectsChanged:nil];
			[svController spellTypeChanged:nil];
			[svController xpPressed:nil];
			/*}else{
				[spellController setFilterPredicate:nil];
			}*/
		}else if([mainTabView indexOfTabViewItem:tabViewItem]==4){
			[self setupBattleStore];
		}
	}else if([tabView isEqualTo:weaponTypeTabView]){
		//check weapon str display.
		if([[weaponController selectedObjects] count]==0)
			return;
		NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];//the current weapon.
		//process weapon feats.
			NSArray *array=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"activeWeaponFeat" substitutionVariables:[NSDictionary dictionary]]
												error:nil];
		if([array count]==0){
			return;//as nothing to process.
		}
		//get the current tab view item.
		NSTabViewItem *currentTab=[tabView selectedTabViewItem];
		NSArray *array2;
		if([tabView indexOfTabViewItem:currentTab]==0){
			//melee
			array2=[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponTypeAffected==2"]];
		}else if([tabView indexOfTabViewItem:currentTab]==2){
			//ranged
			array2=[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponTypeAffected==1"]];
		}
		int i;
		//disable the weapon for the old tab view item.
		if([tabView indexOfTabViewItem:currentTab]!=1){
			for(i=0;i<[array2 count];i++){
				NSManagedObject *feat=[array2 objectAtIndex:i];
				[FeatActions processFeat:feat
								forKeyNo:1
							   onWeapons:[NSArray arrayWithObject:weap]
								forwards:NO];
				[FeatActions processFeat:feat
								forKeyNo:2
							   onWeapons:[NSArray arrayWithObject:weap]
								forwards:NO];
			}
		}
		//now enable feats for the new tab view item.
		if([tabView indexOfTabViewItem:tabViewItem]==0){
			//melee
			array2=[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponTypeAffected==2"]];
		}else if([tabView indexOfTabViewItem:tabViewItem]==2){
			//ranged
			array2=[array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"weaponTypeAffected==1"]];
			//disable shield for ranged.
			[weap setValue:[NSNumber numberWithBool:NO]
					forKey:@"withShield"];
		}
		if([tabView indexOfTabViewItem:tabViewItem]!=1){
			for(i=0;i<[array2 count];i++){
				NSManagedObject *feat=[array2 objectAtIndex:i];
				[FeatActions processFeat:feat
								forKeyNo:1
							   onWeapons:[NSArray arrayWithObject:weap]
								forwards:YES];
				[FeatActions processFeat:feat
								forKeyNo:2
							   onWeapons:[NSArray arrayWithObject:weap]
								forwards:YES];
			}
		}		
	}
	//NSLog(@"will select ended");
}
-(void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem{
	//NSLog(@"app did select tab view item");
	if([tabView isEqualTo:weaponTypeTabView]){
		//check weapon str and attackBonus display.
		if([[weaponController selectedObjects] count]==0)
			return;
		NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];//the current weapon.
		[strWeapField setIntValue:[[strWeapBonus transformedValue:weap] intValue]];
		[attackBonusTF setIntValue:[[abilityAttackBonus transformedValue:weap] intValue]];
		[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"weaponAttackBonus"] intValue]+[[abilityAttackBonus transformedValue:weap] intValue]]
				forKey:@"attackBonus"];
		[magicPlusMS selectItemAtIndex:[[weap valueForKey:@"magicalWeapon"] intValue]];
	}else if([tabView isEqualTo:characterTabView]){
		[self characterStuffNeedsSettingUp];
	}
	//NSLog(@"didSelect end");
}
-(void)characterStuffNeedsSettingUp{
	//NSLog(@"good morning");
	[menuController enableDiceAndLogButtons];
	[menuController defaultButtonsNowOn:YES];
	//now check battle stuff.
	if([[characterController selectedObjects] count]==0){
		[menuController continueBattleNowOn:NO];
		[menuController exitBattleNowOn:NO];
		[menuController restAndGrantXPButtonsNowOn:NO];
		[menuController startNewBattleNowOn:NO];
		[menuController setupCharacterLocked:NO];
		[menuController attackAndSimilarButtonNowOn:NO];
		[menuController spellButtonNowOn:NO];
		[self setupBattleStore];
		//NSLog(@"cannot setup character stuff, no character selected");
		return;
	}
	[self setupBattleStore];
	//process toolbar entries.
	NSArray *toolbarEntries=[[mainScreen toolbar] items];
	//battle disable/enable.
	if([[battleStore valueForKey:@"continueBattle"] boolValue]){
		[menuController continueBattleNowOn:YES];
		[menuController exitBattleNowOn:YES];
		int i;
		for(i=0;i<[toolbarEntries count];i++){
			NSString *identifier=[[toolbarEntries objectAtIndex:i] itemIdentifier];
			if([identifier isEqualToString:@"ContinueBattleTB"] || [identifier isEqualToString:@"ExitBattleTB"]){
				[[toolbarEntries objectAtIndex:i] setEnabled:YES];
			}
		}
	}else{
		[menuController continueBattleNowOn:NO];
		[menuController exitBattleNowOn:NO];
		int i;
		for(i=0;i<[toolbarEntries count];i++){
			NSString *identifier=[[toolbarEntries objectAtIndex:i] itemIdentifier];
			if([identifier isEqualToString:@"ContinueBattleTB"] || [identifier isEqualToString:@"ExitBattleTB"]){
				[[toolbarEntries objectAtIndex:i] setEnabled:NO];
			}
		}
	}
	[mainPartyController setAutomaticallyPreparesContent:NO];
	[mainPartyController prepareContent];
	[mainPartyController setAutomaticallyPreparesContent:YES];
	[enemyPartyController setAutomaticallyPreparesContent:NO];
	[enemyPartyController prepareContent];
	[enemyPartyController setAutomaticallyPreparesContent:YES];
	if([[mainPartyController arrangedObjects] count]>0 && [[enemyPartyController arrangedObjects] count]>0){
		[menuController startNewBattleNowOn:YES];
	}else{
		[menuController startNewBattleNowOn:NO];		
	}
	NSManagedObject *obj=[[characterController selectedObjects] objectAtIndex:0];
	//set up buttons.
	[menuController attackAndSimilarButtonNowOn:YES];
	[menuController restAndGrantXPButtonsNowOn:YES];
	[menuController setupCharacterLocked:![[obj valueForKey:@"canRemove"] boolValue]];
	if([[obj valueForKey:@"spells1"] count]>0 || [[obj valueForKey:@"spells2"] count]>0 || [[obj valueForKey:@"spells3"] count]>0){
		[menuController spellButtonNowOn:YES];
	}else{
		[menuController spellButtonNowOn:NO];
	}
	[self setupClassControlColorsForCharacter:obj];
	int index=[characterTabView indexOfTabViewItem:[characterTabView selectedTabViewItem]];
	if(index==0){
		if([[obj valueForKey:@"charClassName1"] isEqualToString:@""]){
			[charClassName1 setStringValue:@"Choose..."];
		}else{
			[charClassName1 selectItemWithTitle:[obj valueForKey:@"charClassName1"]];
		}
		if([[obj valueForKey:@"charClassName2"] isEqualToString:@""]){
			[charClassName2 setStringValue:@"Choose..."];
		}else{
			[charClassName2 selectItemWithTitle:[obj valueForKey:@"charClassName2"]];
		}
		if([[obj valueForKey:@"charClassName3"] isEqualToString:@""]){
			[charClassName2 setStringValue:@"Choose..."];
		}else{
			[charClassName3 selectItemWithTitle:[obj valueForKey:@"charClassName3"]];
		}
		[level1 setIntValue:[[obj valueForKey:@"charClassLvl1"] intValue]];
		[level2 setIntValue:[[obj valueForKey:@"charClassLvl2"] intValue]];
		[level3 setIntValue:[[obj valueForKey:@"charClassLvl3"] intValue]];
	}else if(index==1){
		[acDexterity setIntValue:[AbilityChanged dexACBonus:obj]];
		[armourCheckPenalty setIntValue:[[obj valueForKey:@"armourCheckPenalty"] intValue]];
		if([AbilityChanged characterTurnsOrRebukesUndead:obj]){
			[turnUndeadOptions setHidden:NO];
			[noTurnUndeadMessage setHidden:YES];
		}else{
			[turnUndeadOptions setHidden:YES];
			[noTurnUndeadMessage setHidden:NO];
		}
	}else if(index==2){
		//check weapon str display.
		if([[weaponController selectedObjects] count]==0)
			return;
		NSManagedObject *weap=[[weaponController selectedObjects] objectAtIndex:0];
		[self updateDefaultWeapon];
		[strWeapField setIntValue:[[strWeapBonus transformedValue:weap] intValue]];
		[attackBonusTF setIntValue:[[abilityAttackBonus transformedValue:weap] intValue]];
		[weap setValue:[NSNumber numberWithInt:[[weap valueForKey:@"weaponAttackBonus"] intValue]+[[abilityAttackBonus transformedValue:weap] intValue]]
				forKey:@"attackBonus"];
		[magicPlusMS selectItemAtIndex:[[weap valueForKey:@"magicalWeapon"] intValue]];
	}else if(index==3){
		if([[characterController selectedObjects] count]!=0){
			if(scController==nil){
				scController=[[SpellClassController alloc] initWithCharController:characterController																			withSpellController:spellController
																  withCharTabView:characterTabView];
			}
			//NSLog(@"magic view to display (app)");
			[scController magicViewOpenedForChar:obj];
		}
	}else if(index==4){
		if([abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==0){
			[skillTable reloadData];
			if([[skillsController arrangedObjects] count]==0){
				return;
			}
			[self setupSkillsForCharacter:obj];
			/*//now set character classes.
			int i;
			NSMutableArray *characterClassNames=[NSMutableArray arrayWithCapacity:3];
			for(i=1;i<4;i++){
				NSString *className=[obj valueForKey:[NSString stringWithFormat:@"charClassName%d",i]];
				if(![className isEqualToString:@"Choose..."]){
					[characterClassNames addObject:className];
				}
			}
			[skillClassChooser removeAllItems];
			if([characterClassNames count]==0){
				[skillClassChooser addItemWithTitle:@"No Classes Available"];
				[skillClassChooser setEnabled:NO];
			}else{
				[skillClassChooser setEnabled:YES];
				for(i=0;i<[characterClassNames count];i++)
					[skillClassChooser addItemWithTitle:[characterClassNames objectAtIndex:i]];
			}
			[self changeSkillClass:nil];*/
			//now set number of skill points left.
			[self calculateRemainingSkillPointsForCharacter:obj];
		}else if([abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==1){
			[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==0"]];
			[self processFeatTable];
		}else if([abilitiesTabView indexOfTabViewItem:[abilitiesTabView selectedTabViewItem]]==2){
			[featsController setFilterPredicate:[NSPredicate predicateWithFormat:@"ability==1"]];
			[self processFeatTable];
		}
	}
}
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)aBool{
	//NSLog(@"app sound finished");
	soundPlaying=NO;
}
/*- (void)textDidEndEditing:(NSNotification *)aNotification{
	NSLog(@"text field stopped editing");
}*/
#pragma mark -
#pragma mark Table Actions
#pragma mark 
-(int)numberOfRowsInTableView:(NSTableView *)aTableView{
	//NSLog(@"app noOfRows");
	if([aTableView isEqualTo:skillsToChooseTable]){
		return 13;
	}else if([aTableView isEqualTo:skillTable]){
		return [[skillsController arrangedObjects] count];
	}else if([aTableView isEqualTo:globalSkillsTable]){
		return [[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"superskill" substitutionVariables:[NSDictionary dictionary]] error:nil] count];
	}
	return nil;
}
-(id)tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
		   row:(int)row{
	//NSLog(@"app objectValueFor...");
	if([aTableView isEqualTo:skillsToChooseTable]){
		NSArray *array=[NSArray arrayWithObjects:@"Strength",@"Dexterity",@"Constitution",@"Intelligence",@"Wisdom",@"Charisma",@"Fortitude",@"Reflex",@"Will",@"Concentration",@"Listen",@"Search",@"Spot",nil];
		return [array objectAtIndex:row];
	}else if([aTableView isEqualTo:skillTable]){
		[skillsController setSortDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"name"
																								  ascending:YES]]];
		NSString *value;
		NSManagedObject *skill=[[skillsController arrangedObjects] objectAtIndex:row];
		if([aTableColumn isEqualTo:[[aTableView tableColumns] objectAtIndex:0]]){
			value=[skill valueForKey:@"name"];
		}else if([aTableColumn isEqualTo:[[aTableView tableColumns] objectAtIndex:1]]){
			value=[NSString stringWithFormat:@"%@",[skill valueForKey:@"total"]];
		}else{
			value=[NSString stringWithFormat:@"%@",[skill valueForKey:@"rank"]];
		}
		if([[skill valueForKey:@"rank"] intValue]==0){
			//grey
			return [[NSAttributedString alloc] initWithString:value attributes:[NSDictionary dictionaryWithObject:[NSColor colorWithDeviceRed:0.4 green:0.4 blue:0.4 alpha:1.0] forKey:NSForegroundColorAttributeName]];
		}else{
			if([[skill valueForKey:@"crossClass"] boolValue]){
				//black
				return [[NSAttributedString alloc] initWithString:value attributes:[NSDictionary dictionaryWithObject:[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0] forKey:NSForegroundColorAttributeName]];
			}else{
				//red
				return [[NSAttributedString alloc] initWithString:value attributes:[NSDictionary dictionaryWithObject:[NSColor colorWithDeviceRed:0.79 green:0.152 blue:0.0 alpha:1.0] forKey:NSForegroundColorAttributeName]];
			}
		}
	}else if([aTableView isEqualTo:globalSkillsTable]){
		return [[[[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"superskill" substitutionVariables:[NSDictionary dictionary]] error:nil] valueForKey:@"name"] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:row];
	}
	return nil;
}
#pragma mark -
#pragma mark File Preferences
#pragma mark 
//open file preferences.
-(IBAction)showFilePreferences:(id)sender{
	if([mainScreen isVisible] && [mainScreen isKeyWindow]){
		[NSApp beginSheet:fileOptionsSheet
		   modalForWindow:mainScreen
			modalDelegate:self
		   didEndSelector:nil
			  contextInfo:NULL];
	}else{
		[fileOptionsSheet makeKeyAndOrderFront:self];
	}
}
-(IBAction)closeFilePreferences:(id)sender{
	[fileOptionsSheet orderOut:sender];
	[NSApp endSheet:fileOptionsSheet];
}
#pragma mark -
#pragma mark BattleStore
#pragma mark 
-(NSManagedObject *)battleStore{
	[self setupBattleStore];
	return battleStore;
}
-(BOOL)setupBattleStore{
	if(battleStore==nil){
		//check if attached sheet.
		if([mainScreen attachedSheet]!=nil){
			return NO;
		}
		//set up battle controller (here is the best place I think...).
		NSPersistentDocument *doc=[[NSDocumentController sharedDocumentController] currentDocument];
		if(doc==nil){
			NSLog(@"currentDocument playing up.");
			if([[NSApp orderedDocuments] count]>0){
				doc=[[NSApp orderedDocuments] objectAtIndex:0];
			}
			if(doc==nil){
				NSLog(@"currentDocument playing up, and order docs playing up too.");
			}
		}
		mObjC=[doc managedObjectContext];
		model=[[mObjC persistentStoreCoordinator] managedObjectModel];
		//set up character classes (as required)
		[characterController setAutomaticallyPreparesContent:NO];
		[characterController prepareContent];
		[characterController setAutomaticallyPreparesContent:YES];
		[spellController setAutomaticallyPreparesContent:NO];
		[spellController prepareContent];
		[spellController setAutomaticallyPreparesContent:YES];
		NSArray *array = [mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"battlePosition" substitutionVariables:[NSDictionary dictionary]]
											  error:nil];
		if([array count]==0){
			battleStore=[theBattleController newObject];
			[battleStore setValue:[NSNumber numberWithInt:100]
						   forKey:@"fileVersion"];//setup version.
				[battleStore setValue:[NSNumber numberWithInt:100]
							   forKey:@"minSupportedVersion"];
				[battleStore setValue:@"1.3"
							   forKey:@"shortMinSupportedVersion"];
				[theBattleController addObject:battleStore];
				[doc updateChangeCount:NSChangeCleared];
				postModelSetupDone=YES;
		}else{
			if([array count]>1){
				NSLog(@"error, multiple battleStores in the current file, deleting excess ones.");
				int i;
				for(i=1;i<[array count];i++){
					[mObjC deleteObject:[array objectAtIndex:i]];
				}
			}
			battleStore=[array objectAtIndex:0];
			if([[theBattleController arrangedObjects] count]==0){
				[theBattleController addObjects:[NSArray arrayWithObject:battleStore]];
			}
			//check file version
			if([[[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleVersion"] intValue]<[[battleStore valueForKey:@"minSupportedVersion"] intValue]){
				NSBeginAlertSheet(@"Document incompatible with this version", @"Close", nil, nil, mainScreen, self,nil,@selector(unsupportedDidEnd:returnCode:contextInfo:),NULL,[NSString stringWithFormat:@"This version of D&D Manager (%@) is too old to open this file as unfortunately version %@ is required. Please download a newer version from http://www.erasersoft.com",[[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleShortVersionString"],[battleStore valueForKey:@"shortMinSupportedVersion"]]);
				return YES;
			}
		}
		NSError *error=nil;
		NSArray *spells=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"NewSpell" substitutionVariables:[NSDictionary dictionary]] error:&error];
		if(error!=nil){
			NSLog(@"error=%@",error);
		}
		//NSLog(@"battleStore created");
		if(([[characterController arrangedObjects] count]>0 || [spells count]>0) && !postModelSetupDone){
			[self setupCharacterClasses];
			//process any required updates here.
			if([[battleStore valueForKey:@"fileVersion"] intValue]<100){
				needsCustomCharToDisplay=NO;
				if(updateController==nil){
					updateController=[[UpdateController alloc] initWithBattleStore:battleStore
														   withCharacterController:characterController
																	withMainWindow:mainScreen];
				}
				[updateController runUpdates];
			}
			//NSLog(@"hi");
			[updateController versionOnePointFourBasicProcessing];
		}
		//NSLog(@"finished!");
		//NSLog(@"setting file version");
		[battleStore setValue:[NSNumber numberWithInt:100]
					   forKey:@"fileVersion"];
		[battleStore setValue:[NSNumber numberWithInt:100]
					   forKey:@"minSupportedVersion"];
		[battleStore setValue:@"1.4"
					   forKey:@"shortMinSupportedVersion"];
		/*** SET UP STUFF THAT NEEDS DOING ONCE THE NIB IS FULLY LOADED HERE***/
		//set up log.
		NSString *str=[battleStore valueForKey:@"eventLog"];
		if(str==nil){
			str=[NSString stringWithFormat:@"==%@==",[[NSDate date] description]];
		}else{
			str=[str stringByAppendingFormat:@"\n\n==%@==",[[NSDate date] description]];
		}
		[battleStore setValue:str
					   forKey:@"eventLog"];
		//clearly not in the right place.
		[doc updateChangeCount:NSChangeCleared];
		[mainScreen setDocumentEdited:NO];
		//NSString *string=[NSString stringWithFormat:@"%@",4];
		postModelSetupDone=YES;
		//NSLog(@"DONE%@",10);
		return YES;
	}
	return NO;
}
-(void)setupDomainClasses{
	NSArray *domainClasses=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"domainClass" substitutionVariables:[NSDictionary dictionary]]
												 error:nil];
	NSArray *dcNames=[domainClasses valueForKey:@"name"];
	NSArray *domainNames=[[NSUserDefaults standardUserDefaults] stringArrayForKey:@"domains"];
	int i;
	for(i=0;i<[domainNames count];i++){
		int j;
		BOOL foundObject=NO;
		NSString *currentDomain=[domainNames objectAtIndex:i];
		for(j=0;j<[dcNames count];j++){
			if([[dcNames objectAtIndex:j] isEqualToString:currentDomain]){
				foundObject=YES;
				break;
			}
		}
		if(!foundObject){
			NSManagedObject *newDomain=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"DomainClass"]
												insertIntoManagedObjectContext:mObjC];
			[newDomain setValue:currentDomain
						 forKey:@"name"];
			[newDomain setValue:[NSNumber numberWithBool:YES]
						 forKey:@"castsSpells"];
		}
	}
	//now setup spellSubviewController
	if(scController!=nil){
		[[scController currentSubview] setupDomainsList];
	}
}
-(void)setupCharacterClasses{
	[self setupDomainClasses];
	//check if character classes exist, if so return.
	if([[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"characterClass" substitutionVariables:[NSDictionary dictionary]]
							 error:nil] count]>0){
		return;
	}
	//Barbarian
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"willMajor"];
		[cc setValue:@"Barbarian"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:12]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
	}
	//Bard
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"willMajor"];
		[cc setValue:@"Bard"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:6]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:6]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:6]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"divineSpell"];
		[cc setValue:@"Charisma"
			  forKey:@"keyAttribute"];
	}
	//Cleric
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"willMajor"];
		[cc setValue:@"Cleric"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:8]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"turnsUndead"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:9]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"divineSpell"];
		[cc setValue:@"Wisdom"
			  forKey:@"keyAttribute"];

	}
	//Druid
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"willMajor"];
		[cc setValue:@"Druid"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:8]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:9]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"divineSpell"];
		[cc setValue:@"Wisdom"
			  forKey:@"keyAttribute"];

	}
	//Fighter
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"willMajor"];
		[cc setValue:@"Fighter"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:10]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//bonus feats
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"bonusFeatAtLevel1"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"levelsPerBonusFeat"];
	}
	//Monk
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"willMajor"];
		[cc setValue:@"Monk"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:8]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//bonus feats.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"bonusFeatAtLevel1"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"levelsPerBonusFeat"];
		[cc setValue:[NSNumber numberWithInt:5]
			  forKey:@"maxLevelOfBonusFeats"];
	}
	//Paladin
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"willMajor"];
		[cc setValue:@"Paladin"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:10]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"turnsUndead"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"turnsAsLevelMinusThree"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"divineSpell"];
		[cc setValue:@"Wisdom"
			  forKey:@"keyAttribute"];

	}
	//Ranger
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"willMajor"];
		[cc setValue:@"Ranger"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:8]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:6]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"divineSpell"];
		[cc setValue:@"Wisdom"
			  forKey:@"keyAttribute"];
	}
	//Rogue
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"willMajor"];
		[cc setValue:@"Rogue"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:6]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:8]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:1]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
	}
	//Sorcerer
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"willMajor"];
		[cc setValue:@"Sorcerer"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:9]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"divineSpell"];
		[cc setValue:@"Charisma"
			  forKey:@"keyAttribute"];
	}
	//Wizard
	if(1){
		NSManagedObject *cc=[[NSManagedObject alloc] initWithEntity:[[model entitiesByName]  objectForKey:@"CharacterClass"]
									 insertIntoManagedObjectContext:mObjC];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"fortitudeMajor"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"reflexMajor"];
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"willMajor"];
		[cc setValue:@"Wizard"
			  forKey:@"name"];
		[cc setValue:[NSNumber numberWithInt:4]
			  forKey:@"sizeOfHD"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"skillPointsPerLevel"];
		[cc setValue:[NSNumber numberWithInt:2]
			  forKey:@"baseAttackType"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"turnsUndead"];
		//spell stuff.
		[cc setValue:[NSNumber numberWithBool:YES]
			  forKey:@"castsSpells"];
		[cc setValue:[NSNumber numberWithInt:0]
			  forKey:@"minimumSpellLevel"];
		[cc setValue:[NSNumber numberWithInt:9]
			  forKey:@"maximumSpellLevel"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"allSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"healOrHarmSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"summoningSpontaneous"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"castsDomainSpells"];
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"divineSpell"];
		[cc setValue:@"Intelligence"
			  forKey:@"keyAttribute"];
		//bonus feats
		[cc setValue:[NSNumber numberWithBool:NO]
			  forKey:@"bonusFeatAtLevel1"];
		[cc setValue:[NSNumber numberWithInt:5]
			  forKey:@"levelsPerBonusFeat"];
	}
}
-(void)convertAbilityBonusSpellsToWorkWithVersionOnePointFourWithExistingTransferred:(BOOL)transferred{
	NSArray *array=[mObjC executeFetchRequest:[model fetchRequestFromTemplateWithName:@"character" substitutionVariables:[NSDictionary dictionary]] error:nil];
	//NSLog(@"array.count=%d",[array count]);
	int j;
	for(j=0;j<[array count];j++){
		NSManagedObject *obj=[array objectAtIndex:j];
		NSArray *spellLevels=[[obj valueForKey:@"spellLevel"] allObjects];
		int i;
		for(i=0;i<[spellLevels count];i++){
			NSManagedObject *spellLevel=[spellLevels objectAtIndex:i];
			int level=[[spellLevel valueForKey:@"level"] intValue];
			int newValue=[AbilityChanged bonusSpellsForCharacter:obj
											   forCharacterClass:[spellLevel valueForKey:@"characterClass"] 
														forLevel:level];
			if(transferred){
				int oldValue=[[spellLevel valueForKey:@"abilityBonusSpells"] intValue];
				[spellLevel setValue:[NSNumber numberWithInt:oldValue+[[spellLevel valueForKey:@"miscBonusSpells"] intValue]-newValue] forKey:@"miscBonusSpells"];
			}
			if(level==0){
				[spellLevel setValue:[NSNumber numberWithInt:0]
							  forKey:@"abilityBonusSpells"];
			}else{
				[spellLevel setValue:[NSNumber numberWithInt:newValue]
							  forKey:@"abilityBonusSpells"];
			}
		}
	}
}
-(void)unsupportedDidEnd:(NSWindow *)panel
			  returnCode:(int)returnCode
			 contextInfo:(void *)contextInfo{
	[characterTable setDelegate:self];
	[[[NSDocumentController sharedDocumentController] currentDocument] close];
}
#pragma mark -
#pragma mark Dealloc
#pragma mark 
-(void)dealloc{
	if(battleController!=nil){
		[battleController release];
	}
	if(diceController!=nil){
		[diceController release];
	}
	if(scController!=nil){
		[scController release];
	}
	[super dealloc];
}
@end
